2011-06-05 56 views
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)

回答

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(); 
} 
+1

應該在失敗時返回空列表 – ysth 2011-06-06 02:40:33

+0

偉大的想法。我應用了你的建議。 – DavidO 2011-06-06 03:42:30

+1

這是非常可讀的。我喜歡!我不知道全部功能或列表模塊。感謝您的迴應。 – yarian 2011-06-06 14:01:26

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並不難實現。

+0

非常感謝你。這正是我所期待的。後續問題雖然。那麼你會如何使用@results? 因此,如果我要添加print @results,那麼在最後使用大括號後,它會炸燬「全球符號需要明確的包裝」。 你如何從循環內部傳遞一個結果,以便它可以在外部訪問? – yarian 2011-06-06 01:55:56

+0

@Yarian:在循環之前聲明:'my @results;' – ysth 2011-06-06 02:26:52

+0

哦,哇....謝謝! – yarian 2011-06-06 02:39:33