【问题标题】:Searching for indices of consecutive elements in an array搜索数组中连续元素的索引
【发布时间】:2011-09-08 22:45:35
【问题描述】:

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

【问题讨论】:

    标签: arrays perl search elements


    【解决方案1】:

    一种天真的方法:

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

    【讨论】:

    • 非常感谢。这正是我一直在寻找的。跟进问题。之后你将如何使用@results?所以在你最后一个花括号之后,如果我要添加 print @results;它会因“全局符号需要显式包”而爆炸。如何从循环内部传递结果,以便在循环外部访问它?
    • @Yarian:在循环之前声明它:my @results;
    【解决方案2】:

    这是一个通用的解决方案。这使用 List::MoreUtils 中的 'all' 函数来减少对真/假结果的比较,这稍微简化了逻辑。

    我把它变成了一个 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 ();
    }
    

    【讨论】:

    • 失败时应该返回一个空列表
    • 好主意。我采纳了你的建议。
    • 这很易读。我喜欢!我不知道 all 函数或 List 模块。感谢您的回复。
    猜你喜欢
    • 2020-02-08
    • 2016-05-24
    • 2015-04-18
    • 2011-09-12
    • 2017-04-12
    • 2021-06-03
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多