2012-06-13 67 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中,如果沒有將它添加到新的名稱列表中。

相關問題