搜索数组中连续元素的索引

时间:2011-06-05 23:16:39

标签: arrays perl search elements

所以我有一个数组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)

2 个答案:

答案 0 :(得分:4)

一种天真的方法:

@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并不难实现。

答案 1 :(得分:2)

这是一般解决方案。这使用了List :: MoreUtils中的'all'函数来减少与true / false结果的比较,这简化了逻辑。

我把它放到一个sub的形式,你传递对任何两个数组的引用。传递给函数的第一个数组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 ();
}