Как выполнить поиск в массиве Perl для соответствующей строки?
каков самый умный способ поиска через массив строк для соответствующей строки в Perl?
одно предостережение, я хотел бы, чтобы поиск был нечувствительным к регистру
так "aAa"
будет ("aaa","bbb")
7 ответов
это зависит от того, что вы хотите, чтобы поиск сделать:
-
если вы хотите найти все матчи используйте встроенный grep:
my @matches = grep { /pattern/ } @list_of_strings;
-
если вы хотите найти первый матч используйте
first
на Список:: Util:use List::Util 'first'; my $match = first { /pattern/ } @list_of_strings;
-
если вы хотите найти количество всех матчей используйте
true
in Список::MoreUtils:use List::MoreUtils 'true'; my $count = true { /pattern/ } @list_of_strings;
-
если вы хотите знать индекс первого матча используйте
first_index
на Список::MoreUtils:use List::MoreUtils 'first_index'; my $index = first_index { /pattern/ } @list_of_strings;
-
если вы хотите просто знать если бы была спичка, но вам все равно, какой элемент это был или его значение, используйте
any
на Список:: Util:use List::Util 1.33 'any'; my $match_found = any { /pattern/ } @list_of_strings;
все эти примеры похожи вещи в их ядре, но их реализации были сильно оптимизированы, чтобы быть быстрыми, и будут быстрее, чем любая реализация pure-perl, которую вы могли бы написать сами с grep, карта или цикл.
обратите внимание, что алгоритм выполнения цикла является отдельной проблемой, чем выполнение отдельных совпадений. Для сопоставления строк без учета регистра, вы можете просто использовать i
флаг в шаблон: /pattern/i
. Вы обязательно следует прочитать perldoc perlre если вы ранее этого не делали.
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!"
Если вы будете делать много поиск в массиве, и соответствие всегда определяется как эквивалентность строк, затем вы можете нормализовать свои данные и использовать хэш.
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
или другие требования, которые могут быть выполнены путем нормализации (например, нечувствительность к регистру).
#!/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;
Perl string match также может использоваться для простого Да / нет.
my @foo=("hello", "world", "foo", "bar");
if ("@foo" =~ /\bhello\b/){
print "found";
}
else{
print "not found";
}
только для логического результата матча или для количества вхождений вы можете использовать:
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'
не требуется использовать модуль.
Конечно, это менее "расширяемый" и универсальный, как и некоторый код выше.
Я использую это для интерактивного пользователя ответы на матче против предопределенный набор случае unsensitive ответы.