2012-06-13 68 views
2

我有两个数组,@names@employees,这些数组填充了表示名称的字符串。 @names是2维的,它引用了匿名数组,但我们关心的数据的位置是@names[i][0]。我想循环通过@names并找到哪些名字不在@employees比较两个数组,删除匹配的项目

起初我以为通过向后循环@names,将它与@employees相比较并删除@names的任何匹配都可以,但我遇到了一些错误。下面是我有:

for my $i (reverse(0 .. $#names)) { 
    foreach my $employee (@employees) { 
    if ($names[$i][0] eq $employee) { # line 67 
     splice(@names, $i, 1); 
    } 
    } 
} 

我碰到这个错误:

Use of uninitialized value in string eq at script.pl line 67, line 2.

中的字符串数组中的所有规定。所以我猜测这是由于我在循环中删除数组中的元素造成的,但我认为通过向后循环数组可以防止发生这样的问题。

那么我在哪里我的循环错了?另外,我一直在为这个循环而努力,并暗示我的整个思维过程都有问题。有没有更好的方法来做到这一点?

+0

可能重复的[如何查找在一个数组中但不是另一个在Perl中的元素?](http://stackoverflow.com/questions/6714667/how-can-i-find-elements-这是一个数组,但不是另一个perl) – Flimzy

回答

9

没有理由在这里显式循环。你想过滤名称:这是一个grep。你想检查成员资格:这也可以通过grep来完成。

@names = grep {my $name = $$_[0]; not grep $_ eq $name, @employees} @names; 

重复扫描内部阵列并不是特别有效;它可以通过提前预先填充一个集合(真正的散列)来避免。

my %employees = map +($_ => 1), @employees; 
@names = grep !$employees{$$_[0]}, @names; 
+0

直接使用该值不是更好吗? @names = grep!$ employees {$ _},@names; –

+0

@DanLittlejohn根据OP的说法,'@ names'是一个二维数组,所以'$ _'仍然是一个列表引用。对它进行字符串化(这是散列键发生的情况)没有用处。 – ephemient

+0

这给出了一个'不能使用字符串作为ARRAY参考,而“严格参考”在使用中' – Droidzone

0

不提供代码,我会做的是返回一个新的@name列表。对于@names中的每个名称,检查它是否在@employees中,如果没有将它添加到新的名称列表中。

相关问题