2013-07-31 318 views
2

一個子我有兩個陣列:高效的方式,如果數組元素是元素的另一個數組

  1. @array1包含blah1通過blah100
  2. @array2包含Name: creating "blah1"Name: creating "blah100"

我需要檢查從@array1每個元素在@array2Name: creating部分的方式獲得。

確保@array1中的所有元素都在@array2中的最佳途徑是什麼?

也許使用正則表達式進行匹配,同時循環使用@array1針對@array2
還有更快的方法嗎?

請問array_diff,intersectunique是否在陣列中有噪音的字符串時工作?

OR

也許操縱@數組2以便它能夠爲每個數據擺脫Name: creating部分?

哪種方式會更快?

+0

待辦事項你有任何控制這些數組的創建?或者你從某個地方得到它們。 – user4035

+0

你想要什麼結果?布爾意思是「匹配」還是「不匹配」,或者還有其他什麼要求? – AdrianHHH

+0

無法控制這些數組的創建。 @ user4035 – ealeon

回答

4
die if @array1 != @array2; 
for (0..$#array1) { 
    die if $array2[$_] ne qq{Name: creating "$array1[$_]"}; 
} 

,或者如果名稱部分是可變的,

die if @array1 != @array2; 
for (0..$#array1) { 
    die if $array2[$_] !~ /: creating "\Q$array1[$_]\E"$/; 
} 
+0

如果它們被排序。否則,可以對其進行排序。 – Qtax

+0

@Qtax,真,儘管有比解決方案更好的解決方案。對於100個元素,儘管「複雜度」更高,排序可能會更快。 – ikegami

+0

僅僅因爲兩個數組中的元素數量不相同或者其中一個元素不匹配,他的程序爲什麼會死亡(或者不得不陷入死亡)? @Qtax這個問題似乎表明數據是按順序排列的(數組blah1到blah100),以及它們是否是,排序只會將它們按錯誤的順序排除,直到'Name:creating'前綴被移除。 –

1

我會用同樣的規則都列進行排序,然後通過一個比較之一。

use strict; 
use warnings; 

sub checkall{ 
my @array1 = @{shift}; 
my @array2 = @{shift}; 

my @sorted1 = sort{ $a <=> $b } @array1; 
my @sorted2 = sort{ $a <=> $b } @array2; 

if($#sorted1 == $#sorted2){ 
    for(0 .. $#sorted1) 
    { 
    #print $sorted1[$_] ."->". $sorted2[$_] ."\n"; #uncomment to see the comparison 
    return "doesn't match!" if not $sorted1[$_] eq $sorted2[$_]; 
    } 
    return "ok!"; 
}else 
    { 
    return "not same size!"; 
    } 
} 

my @array1 = (4,2,3,1); 
my @array2 = (1,2,3,4); 
print checkall(\@array1,\@array2); 

另一個版本更接近問題的要求:

sub checkall{ 
    my @array1 = @{shift}; 
    my @array2 = @{shift}; 
    my $aux; 

    my @sorted1 = sort (map{ ($aux) = $_ =~ /Name\: creating \"(.*)\"/g } @array1); 
    my @sorted2 = sort @array2; 

    if($#sorted1 == $#sorted2){ 
     for(0 .. $#sorted1) 
     { 
     #print $sorted1[$_] ."->". $sorted2[$_] ."\n"; #uncomment to see the comparison 
     return "doesn't match!" if not $sorted1[$_] eq $sorted2[$_]; 
     } 
     return "ok!"; 
    }else 
     { 
     return "not same size!"; 
     } 
    } 

所不同的是在創造與地圖和模式的新名單。

+0

這是一個例子,只是把你自己的排序規則和比較。 – AlfredoVR

1

我最好使用映射到需要的部分從所述第二陣列過濾,然後與智能匹配運算符(~~)比較兩個:

#!/usr/bin/perl 

use strict; 
use warnings; 

my @arr1 = qw(blah1 blah2 blah3); 
my @arr2 = ('Name: creating "blah1"','Name: creating "blah2"','Name: creating "blah3"'); 

my @compare = map { local $_ = $_; s/^.+\: creating "([a-zA-Z0-9]+)"/$1/; $_ } @arr2; 

if (@arr1 ~~ @compare){ 
    print "all blahs there\n"; 
} 

在這個例子中其假定兩個陣列已經排序,如果不只是使用「排序」。

+0

什麼是一個整潔的把戲!即時通訊仍在辯論是否採取這種方式,因爲如果arr2「只包含」arr1,即arr2可以在arr1中有更多內容。 – ealeon

+0

什麼是'本地$ _ = $ _; '爲了?我不認爲這是必要的 – doubleDown

+0

'本地$ _ = $ _;'是必要的,因爲我不想更改@ arr2! – marderh

1

示例數據

my @array1 = qw(blah1 blah2); 
my @array2 = split(';', 'Joe: creating "blah1";Bill: creating "blah2"'); 

前兩個以下行對你的問題的解決方案

my @check = map { m/:.*?"(.*)"/g } @array2; 
if (@array1 == @array2 && "@array1" eq "@check") { 
    # note that @array1 == @array2 is only done for efficiency; 
    # it would be sufficient to verify only that 
    # "@array1" eq "@check" 
    print "same\n"; 
} else { 
    print "different\n"; 
} 

注意,它現在是安全的情況下進行排序@array1@check您原始數組不是相應的順序。(排序@array@array2只會是可能破壞可能已經因爲@array2前綴值的名稱有任何命令。)

my @check = map { m/:.*?"(.*)"/g } @array2; 
my $i = 0; 
if (@array1 == @array2) { 
    for (; $i < @array1; $i++) { 
     last if $array1[$i] ne $check[$i]; 
    } 
} else { 
    $i = -1; 
} 
if ($i == @array1) { 
    print "same\n"; 
} else { 
    print "different\n"; 
} 

請注意,這較長的代碼是只有更高效如果你的陣列是而不是相同。如果通常情況下您希望數組的值相同,那麼使用較長的代碼沒有好處。

BTW:正則表達式看起來很粗心,但根據OP它正是我們想要的,特別是如果blah1,blah2等可能包含額外的雙引號。如果我們確定沒有名稱包含引號,那麼我們可以刪除:.*?,只是單獨執行"(.\*)",這會更快。

+0

我的第一個建議的解決方案始終有效。對於我的第二個解決方案,你有點正確。我正確地比較了標量上下文中兩個數組的長度,並正確比較足夠數量的元素以確定它們是否不相同。然而,只比較'$ i'和'@ array1'的捷徑假定'@ array1'中有數據。我將更新以處理'@ array1 == 0'的情況。請注意,OP說「'@ array1'有數據」,實際上,我的兩個解決方案都是正確的。 ;) –

1

相比ikegamisolution

die if @array1 != @array2; 
my $i; 
for my $e (@array1) { 
    die if $array2[$i++] ne qq{Name: creating "$e"}; 
} 

編輯這應該是最快的,但是隻有很少的保證金:

如果字符串的名稱部分是可變的:

die if @array1 != @array2; 
my $i; 
for my $e (@array1) { 
    die if $array2[$i++] !~ m/: creating "\Q$e\E"/; 
} 
+0

請注意,「名稱」不能被認爲是超過「blah1」和「blah2」的文字值。假設其他方案几乎肯定是錯誤的。 –

相關問題