#perl
#perl
Вопрос:
В главе 4, раздел 4.8 (Вычисление объединения, пересечения или различия уникальных списков), в Perl Cookbook приводится этот метод для получения пересечения двух списков целых чисел:
@a = (1, 3, 5, 6, 7, 8);
@b = (2, 3, 5, 7, 9);
...
foreach $e (@a, @b) {
$union{$e} amp;amp; $isect{$e}
}
@union = keys %union;
@isect = keys %isect;
Я хочу, чтобы это было сделано (без учета регистра) для двух списков строк. Любой эффективный метод, пожалуйста?
Ответ №1:
Array::Utils — это то, что вы ищете.
use Array::Utils qw(:all);
my @a = qw( a b c d );
my @b = qw( c d e f );
my @isect = intersect(@a, @b);
print join(",",@isect) . "n";
Это приводит к ожидаемому результату
c,d
Редактировать: Я не заметил, что вы хотели, чтобы это было сделано без учета регистра. В этом случае вы можете заменить @a
на map{lc}@a
(и аналогично на @b
).
Комментарии:
1. Просто для подтверждения, решения, предоставленные из cookbook, не подходят для моей ситуации, главным образом, из-за проблем с хэшированием строк, правильно?
2. На самом деле, нет, решения по предоставленной вами ссылке работают просто отлично, за исключением чувствительности к регистру. Что заставляет вас думать, что они этого не сделают?
3. @Qiang Li — абсолютно неверно. Кулинарная книга использует хэши Perl, которые индексируются строками. Фактически, целые числа в примере неявно преобразуются в строки, когда они используются в качестве хэш-ключей.
Ответ №2:
Наименьшее количество изменений, требуемых от исходного решения. Просто строчные строки.
@a = qw( a b c d );
@b = qw( C D E F );
...
foreach $e (@a, @b) {
$union{lc $e} amp;amp; $isect{lc $e}
}
@union = keys %union;
@isect = keys %isect;
Комментарии:
1. Сбой при
@a=qw(a b c A B C); @b=();
Ответ №3:
Вот один map
/ grep
подход:
my @a = qw(Perl PHP Ruby Python C JavaScript);
my @b = qw(erlang java perl python c snobol lisp);
my @intersection =
grep { defined }
@{ { map { lc ,=> $_ } @a } }
{ map { lc } @b };
# @intersection = qw(Perl Python C)
Ответ №4:
Вы также можете использовать функцию duplicates из модуля List::MoreUtils следующим образом:
use List::MoreUtils qw( duplicates );
my @php56 = qw( json big_int imap );
my @php44 = qw( json imap bcmath );
say $_
for duplicates @php56, @php44;
# Output: json, imap
Это было бы равно пересечению модуля Array::Utils, упомянутого выше.
Комментарии:
1. Те, кто проголосовал против, не могли бы вы, пожалуйста, объяснить причину этого действия, и чем «дубликаты» отличаются от «пересекаться», чтобы мы знали, если уже не знаем.
Ответ №5:
@a = qw(a B c d);
@b = qw(b c D e f);
@c = grep { $f = lc $_; grep lc $_ eq $f, @b } @a;
дает
B c d
1) Я где-то нашел это решение, но не помню где. Если кто-нибудь знает, пожалуйста, дайте мне знать.
2) Я понятия не имею, насколько это эффективно по сравнению с другими решениями.
3) Искренне говоря, я не знаю, как это работает. Почему здесь точка с запятой, а не запятая?