2016-11-23 16 views
1

私は2つのリストがあります:たPerl:2つのリストでペア要素

my @prefixes = ["abc", "def", "ghi", "jklmn"]; 
my @strings = ["abc123", "def456", "jklmnopqrst"]; 

「DEF所属する「ABC」と「def456」に所属する「ABC123」ように私は、各文字列の正しいプレフィックスを見つける必要があります「jklmnopqrst」は「jklmn」に属します。 すべての文字列は@prefixesに接頭辞を含みますが、すべての接頭辞に一致する文字列があります(「ghi」を参照)。

私はこのコードを持っている:

use List::Util qw(first); 
... 
foreach my $str (@strings) { 
    my $prefix = first { $_ eq substr($str, 0, length($_)) } @prefixes; 
    print "$prefix\n"; 
    # do something with $str and $prefix together 
} 

しかし、それは働いていないが、私が間違って何Use of uninitialized value $prefix in concatenation (.) or string

を取得していますか?

更新日:これは簡単な修正です。私はリストを()ではなく[]で初期化しておくべきだった。これを閉じないようにするには、foreachの声明をどのように取り除きますか?

+0

オク、私はダムです。私は()の代わりに()を使って配列を初期化する必要がありました。 – papaiatis

+0

'map'で - しかし' foreach'のように内部を処理する柔軟性はありません。 – zdim

答えて

3

あなたは接頭辞から正規表現パターンを作成し、ハッシュを構築するためにそれを使用することができます

#!/usr/bin/env perl 

use strict; 
use warnings; 

use YAML::XS; 

my @prefixes = qw[abc def ghi jklmn]; 
my @strings = qw[abc123 def456 jklmnopqrst]; 

my ($prefix_re) = map qr/$_/, sprintf(
    '^(?<prefix>%s)', 
    join '|', sort { length $b <=> length $a } @prefixes 
); 

print "$prefix_re\n"; 

my %matches = map { $_ =~ $prefix_re; ($+{prefix}, $_) } @strings; 

print Dump \%matches; 

出力:

abc: abc123 
def: def456 
jklmn: jklmnopqrst

複数の文字列がプレフィックスと一致することができた場合は、することができます一致する文字列のリストに接頭辞をマップする:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use YAML::XS; 

my @prefixes = qw[abc def ghi jklmn]; 
my @strings = qw[abc123 def456 def789 jklmnopqrst]; 

my ($prefix_re) = map qr/$_/, sprintf(
    '^(?<prefix>%s)', 
    join '|', sort { length $b <=> length $a } @prefixes 
); 

print "$prefix_re\n"; 

my %matches; 

for my $str (@strings) { 
    next unless $str =~ $prefix_re; 
    push @{ $matches{ $+{prefix} }}, $str; 
} 

print Dump \%matches; 

出力:

--- 
abc: 
- abc123 
def: 
- def456 
- def789 
jklmn: 
- jklmnopqrst
+1

それは別の素晴らしい解決策です!大いに感謝する! – papaiatis

+0

助けてくれてうれしいです。マッチを保存するのではなく、マッチして処理して移動するだけであれば、メモリの使用量とパフォーマンスの点ではより良いかもしれません。 –

2

foreachの代わりにmapを使用できますが、コードはかなり読みにくくなります。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use List::Util qw/ first /; 

my @prefixes = ("abc", "def", "ghi", "jklmn"); 
my @strings = ("abc123", "def456", "jklmnopqrst"); 

# foreach my $str (@strings) { 
# my $prefix = first { $_ eq substr($str, 0, length($_)) } @prefixes; 
# print $prefix, "\n"; 
# } 

my @found = map { my $str = $_; first { $_ eq substr($str, 0, length($_))} @prefixes } @strings; 

print join("\n", @found), "\n"; 
関連する問題