如何删除与perl中第二个数组中的某个元素相等的数组元素

时间:2011-09-22 22:51:30

标签: perl

只是想知道我是否有两个数组,A和B,如何删除/删除A中也可以在B中找到的那些元素?这样做最有效的方法是什么?

另外,作为一种特殊情况,如果B是A之后grep之后的结果数组,该怎么做?当然,在这种情况下,我们可以在否定条件下进行grep。但是在perl中是否有类似于另一个数组的补充?

谢谢。

6 个答案:

答案 0 :(得分:7)

每当你想到found in时,你可能正在寻找哈希。在这种情况下,您将创建B值的哈希值。然后你会grep A,检查每个元素的哈希值。

my @A = 1..9;
my @B = (2, 4, 6, 8);
my %B = map {$_ => 1} @B;

say join ' ' => grep {not $B{$_}} @A; # 1 3 5 7 9

正如您所看到的,perl通常不会自行维护任何类型的found in表, 所以你必须提供一个。上面的代码可以很容易地包含在一个函数中,但为了提高效率,最好是内联。

答案 1 :(得分:3)

查看List::MoreUtils提供的noneallpartnotall方法。您可以使用此模块中提供的方法执行几乎任何设置操作。

Perl Training Australia

提供了一个很好的教程

答案 2 :(得分:1)

如果您要求最有效的方式:

my @A = 1..9;
my @B = (2, 4, 6, 8);

my %x;
@x{@B} = ();
my @AminusB = grep !exists $x{$_}, @A;

但是你会注意到我和Eric Stromsolution之间的区别仅在于更大的输入。

你可以找到方便的功能方法:

sub complementer {
  my %x;
  @x{@_} = ();
  return sub { grep !exists $x{$_}, @_ };
}

my $c = complementer(2, 4, 6, 8);

print join(',', $c->(@$_)), "\n" for [1..9], [2..10], ...;

# you can use it directly of course
print join(' ', complementer(qw(a c e g))->('a'..'h')), "\n";

答案 3 :(得分:0)

您可能最好使用哈希,但您也可以使用smart matching。窃取Eric Strom的例子,

my @A = 1..9;
my @B = (2, 4, 6, 8);

say join ' ' => grep {not $_ ~~ @B } @A; # 1 3 5 7 9

答案 4 :(得分:0)

同样,您可能最好使用哈希,但您也可以使用Perl6::Junction。再次窃取Eric Strom的例子,

use Perl6::Junction qw(none);

my @A = 1..9;
my @B = (2, 4, 6, 8);

say join ' ' => grep {none(@B) == $_} @A; # 1 3 5 7 9

答案 5 :(得分:-1)

正如Eric Strom已经提到的,每当您需要搜索特定内容时,如果您有哈希值,则总是更容易。

Eric有一个更好的解决方案,但可能很难理解。我希望我的内容更容易理解。

# Create a B Hash

my %BHash;
foreach my $element (@B) {
   $BHash{$element} = 1;
}

# Go through @A element by element and delete duplicates

my $index = 0;
foreach my $element (@A) {
   if (exists $BHash{$element}) { 
      splice @A, $index, 1;    #Deletes $A[$index]
      $index = $index + 1;
   }
}

在第一个循环中,我们只需创建一个由@B中的元素键入的哈希。

在第二个循环中,我们遍历@A中的每个元素,同时跟踪@A中的索引。