Получаем пересечение двух списков строк в Perl без учета регистра

#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) Искренне говоря, я не знаю, как это работает. Почему здесь точка с запятой, а не запятая?