2012-06-13 4 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- that-are-in-one-array-but-not-another-in-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 ref в то время как" строгие refs "в использовании' – Droidzone

0

Без предоставления кода, что бы я сделал, это вернуть новый список @names. Для каждого имени в @names проверьте, находится ли он в @employees, если не добавить его в новый список имен.

Смежные вопросы