Как найти массив Perl для соответствующей строки?

Каков самый умный способ поиска по массиву строк для соответствующей строки в Perl?

Одно предупреждение, я бы хотел, чтобы поиск был нечувствительным к регистру

поэтому "aAa" будет в ("aaa","bbb")

Ответ 1

Думаю,

@foo = ("aAa", "bbb");
@bar = grep(/^aaa/i, @foo);
print join ",",@bar;

сделал бы трюк.

Ответ 2

Это зависит от того, что вы хотите выполнить:

  • если вы хотите найти все соответствия, используйте встроенный grep:

    my @matches = grep { /pattern/ } @list_of_strings;
    
  • если вы хотите найти первое совпадение, используйте first в List::Util:

    use List::Util 'first';  
    my $match = first { /pattern/ } @list_of_strings;
    
  • если вы хотите найти количество совпадений, используйте true в List::MoreUtils:

    use List::MoreUtils 'true';
    my $count = true { /pattern/ } @list_of_strings;
    
  • если вы хотите узнать индекс первого совпадения, используйте first_index в List::MoreUtils:

    use List::MoreUtils 'first_index'; 
    my $index = first_index { /pattern/ } @list_of_strings;
    
  • если вы хотите просто знать , если было совпадение, но вам все равно, какой элемент он или его значение, используйте any в List:: Util:

    use List::Util 1.33 'any';
    my $match_found = any { /pattern/ } @list_of_strings;
    

Все эти примеры выполняют аналогичные вещи по своей сути, но их реализации сильно оптимизированы, чтобы быть быстрыми и будут быстрее, чем любая реализация pure-perl, которую вы могли бы написать grep, map или для цикла.


Обратите внимание, что алгоритм выполнения цикла является отдельной проблемой, чем выполнение отдельных совпадений. Чтобы совместить строковый регистр без учета регистра, вы можете просто использовать флаг i в шаблоне: /pattern/i. Вы должны обязательно прочитать perldoc perlre, если вы этого еще не сделали.

Ответ 3

Perl 5.10+ содержит оператор "smart-match" ~~, который возвращает true, если определенный элемент содержится в массиве или хеше, а false, если он не отображается (см. perlfaq4):

Приятно то, что он также поддерживает регулярные выражения, что означает, что с учетом вашего без учета регистра можно легко позаботиться:

use strict;
use warnings;
use 5.010;

my @array  = qw/aaa bbb/;
my $wanted = 'aAa';

say "'$wanted' matches!" if /$wanted/i ~~ @array;   # Prints "'aAa' matches!"

Ответ 4

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my @bar = qw(aaa bbb);
my @foo = grep {/aAa/i} @bar;

print Dumper \@foo;

Ответ 5

Если вы будете выполнять много запросов в массиве, соответствие И всегда определяется как эквивалентность строк, тогда вы можете нормализовать свои данные и использовать хэш.

my @strings = qw( aAa Bbb cCC DDD eee );

my %string_lut;

# Init via slice:
@string_lut{ map uc, @strings } = ();

# or use a for loop:
#    for my $string ( @strings ) {
#        $string_lut{ uc($string) } = undef;
#    }


#Look for a string:

my $search = 'AAa';

print "'$string' ", 
    ( exists $string_lut{ uc $string ? "IS" : "is NOT" ),
    " in the array\n";

Позвольте мне подчеркнуть, что поиск хэша хорош, если вы планируете делать много запросов в массиве. Кроме того, он будет работать только в том случае, если совпадение означает $foo eq $bar или другие требования, которые могут быть удовлетворены посредством нормализации (например, нечувствительность к регистру).

Ответ 6

Соответствие строк в Perl также может использоваться для простого да/нет.

my @foo=("hello", "world", "foo", "bar");

if ("@foo" =~ /\bhello\b/){
    print "found";
}
else{
    print "not found";
}

Ответ 7

Для всего лишь результата логического совпадения или для количества вхождений вы можете использовать:

use 5.014; use strict; use warnings;
my @foo=('hello', 'world', 'foo', 'bar', 'hello world', 'HeLlo');
my $patterns=join(',',@foo);
for my $str (qw(quux world hello hEllO)) {
    my $count=map {m/^$str$/i} @foo;
    if ($count) {
        print "I found '$str' $count time(s) in '$patterns'\n";
    } else {
        print "I could not find '$str' in the pattern list\n"
    };
}

Вывод:

I could not find 'quux' in the pattern list
I found 'world' 1 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
I found 'hello' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
I found 'hEllO' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'

Не требуется использовать модуль.
Конечно, это менее "расширяемый" и универсальный, как некоторый код выше.
Я использую это для интерактивных ответов пользователей, чтобы соответствовать предопределенному набору нечувствительных ответов на случай.