web-dev-qa-db-ja.com

Perl配列で一致する文字列を検索するにはどうすればよいですか?

Perlで文字列の配列を検索して一致する文字列を検索する最も賢い方法は何ですか?

注意点として、大文字と小文字を区別しない検索をお願いします

そう "aAa"("aaa","bbb")

36
Mike

私は推測する

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

トリックを行います。

29
Peter Tillemans

検索で何をしたいかによって異なります。

  • すべての一致を検索する場合は、組み込みの grep を使用します。

    my @matches = grep { /pattern/ } @list_of_strings;
    
  • 最初の一致を見つけるには、 List :: Utilfirstを使用します:

    use List::Util 'first';  
    my $match = first { /pattern/ } @list_of_strings;
    
  • すべての一致のカウントを検索する場合は、 List :: MoreUtilstrueを使用します。

    use List::MoreUtils 'true';
    my $count = true { /pattern/ } @list_of_strings;
    
  • 最初の一致のインデックスを知りたい場合List :: MoreUtilsfirst_indexを使用します。

    use List::MoreUtils 'first_index'; 
    my $index = first_index { /pattern/ } @list_of_strings;
    
  • 単純に一致したかどうかを知りたいが、それがどの要素であるか、またはその値を気にしない場合は、anyを使用します。 in リスト::ユーティリティ

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

これらの例はすべてコアで同様のことを行いますが、実装は高速になるように大幅に最適化されており、 grepmap または for loop


ループを実行するアルゴリズムは、個々の一致を実行することとは別の問題であることに注意してください。文字列を大文字と小文字を区別せずに一致させるには、パターンでiフラグを使用できます:/pattern/iperldoc perlre をまだ読んでいない場合は、必ず読んでください。

143
Ether

Perl 5.10以降には、「スマートマッチ」演算子~~は、特定の要素が配列またはハッシュに含まれている場合は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!"
29
Zaid

配列のmany検索を行う場合、[〜#〜] and [〜#〜]は常に一致します文字列の等価として定義されている場合、データを正規化してハッシュを使用できます。

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
daotoad
#!/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
Alex Reynolds

Perl文字列一致は、単純なyes/noにも使用できます。

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

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

単なるブール一致結果または発生回数の場合、次を使用できます。

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'

seモジュールを必要としません。
もちろん、上記のコードのように「拡張可能」ではなく、多用途です。
これは、インタラクティブなユーザーの回答に使用し、大文字と小文字を区別しない事前定義済みの回答のセットと照合します。

1