2013-07-31 284 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”的文字值。假设其他方案几乎肯定是错误的。 –

相关问题