搜索連續元素的索引所以我有一個數組my @a = (a,b,c,d,e,f)
而另一個數組my @b = (c,d,e)
陣列中的
我想找到是否有@a
連續三個要素匹配在@b
這一點。 然後,如果有的話,我想獲得這些元素居住的指數。
所以在上面的情況下,我想獲得一個數組,如(2,3,4)
。
又如:
my @a = (1,2,3,4,5)
my @b = (2,3)
輸出:(1,2)
搜索連續元素的索引所以我有一個數組my @a = (a,b,c,d,e,f)
而另一個數組my @b = (c,d,e)
陣列中的
我想找到是否有@a
連續三個要素匹配在@b
這一點。 然後,如果有的話,我想獲得這些元素居住的指數。
所以在上面的情況下,我想獲得一個數組,如(2,3,4)
。
又如:
my @a = (1,2,3,4,5)
my @b = (2,3)
輸出:(1,2)
這裏是一個通用的解決方案。它使用List :: MoreUtils中的'all'函數將比較結果減少爲真/假結果,從而簡化了邏輯。
我把它放到你傳遞給任何兩個數組的引用的子表單中。傳遞給函數的第一個數組ref應該是超集,第二個數組ref應該引用子集數組。
我喜歡這個解決方案,它可以應用於任何兩個簡單的數組(例如,它不限於尋找一個雙元素子集)。我確實選擇了元素(eq)的字符串比較,而不是數字(==)。這種方式,如果你有非數字元素,它的工作原理。但是,它會將'00'和'0'評估爲不相等(因爲它們不是相同的字符串)。如果您喜歡數字比較,只需找到'eq'並將其更改爲'=='即可。
下面的代碼:
use 5.010_001;
use strict;
use warnings;
use List::MoreUtils qw/all/;
my @array_a = qw/1 2 3 4 5/;
my @array_b = qw/2 3/;
{
local $, = " ";
my(@results) = find_group(\@array_a, \@array_b);
say "Success at ", @results if @results;
}
sub find_group {
my($array_1, $array_2) = @_;
foreach my $array_1_idx (0 .. $#{$array_1}) {
my $moving_idx = $array_1_idx;
return $array_1_idx .. ($moving_idx - 1) if
all { $_ eq $array_1->[$moving_idx++] } @{$array_2};
}
return();
}
天真的方法:
@A = 1..5;
@B = 2..3;
A_LOOP:
for my $a_index (0..$#A) {
for my $b_index (0..$#B) {
next A_LOOP unless $A[$a_index+$b_index] eq $B[$b_index];
}
@results = map $a_index+$_, 0..$#B;
last;
}
如果這還不夠快(不可能的,因爲你的例子), Boyer-Moore並不難實現。
應該在失敗時返回空列表 – ysth 2011-06-06 02:40:33
偉大的想法。我應用了你的建議。 – DavidO 2011-06-06 03:42:30
這是非常可讀的。我喜歡!我不知道全部功能或列表模塊。感謝您的迴應。 – yarian 2011-06-06 14:01:26