检查数组元素是否是另一个数组中元素的子字符串的有效方法

时间:2013-07-31 21:02:03

标签: arrays perl

我有两个数组:

  1. @array1包含blah1blah100
  2. @array2包含Name: creating "blah1"Name: creating "blah100"
  3. 我需要检查@array1中的每个元素是否在@array2中,但Name: creating部分正在阻碍。

    确保@array1中的所有元素都在@array2中的最佳途径是什么?

    也许在使用@array1@array2进行循环时使用正则表达式进行匹配? 还有另一种更快的方法吗?

    当其中一个阵列中存在嘈杂的字符串时,array_diffintersectunique是否正常工作?

    OR

    可能会操纵@ array2,以便它为每个数据摆脱Name: creating部分?

    哪种方式会更快?

5 个答案:

答案 0 :(得分:4)

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

Name 部分是变量,

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

答案 1 :(得分: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!";
      }
    }

不同之处在于创建了一个包含地图和模式的新列表。

答案 2 :(得分:1)

我使用map来过滤第二个数组中所需的部分,然后将它们与智能匹配运算符进行比较(~~):

#!/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";
}

在这个例子中假设两个数组都已经排序,如果不是只使用“sort”。

答案 3 :(得分: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等可能包含额外的双引号。如果我们确定没有名称包含引号,那么我们可以删除:.*?并单独执行"(.\*)",这会更快。

答案 4 :(得分:1)

这应该是最快的,但与ikegami solution {{3}}

相比只有很小的余量
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"/;
}