【问题标题】:In perl, checking an array for a value and removing it if exists for each value of another array在 perl 中,检查一个数组的值,如果另一个数组的每个值都存在,则将其删除
【发布时间】:2010-08-11 07:00:47
【问题描述】:

基本上,我有一个数组,比如说@badvalues

我有另一个数组,比如说@values

基本上,我想要这个:

对于@badvalues中的每个元素

  • 查看是否在@values
  • 如果是,删除它
  • 最终,我应该得到数组@values,不包含数组@badvalues 中的任何元素,或者一个新数组@goodvalues,包含@values 中不是元素的每个元素的@badvalues

我知道这听起来很简单,也许是因为我累了,但是我在四处寻找这个问题时似乎找不到明确的答案。

【问题讨论】:

标签: arrays perl


【解决方案1】:
# Get only bad values
my %values = map {$_=>1} @values;
my @new_badvalues = grep { !$values{$_} } @badvalues;

# Get only good values
my %badvalues = map {$_=>1} @badvalues;
my @goodvalues = grep { !$badvalues{$_} } @values;

# An alternative
@badvalues{@badvalues} = ();
foreach $item (@values) {
    push(@goodvalues, $item) unless exists $badvalues{$item};
}

有关更完整的参考,请参阅“Perl Cookbook”的“第 4.7 章。在一个数组中查找元素而不是另一个数组”

【讨论】:

  • 谢谢!给你的虚拟巧克力蛋糕。
  • Stackoverflow:从 2010 年开始同时引用杂草和 Perl!
【解决方案2】:

如果您有现代 Perl 版本,例如 >= 5.10.1,那么您也可以这样做:

my @final_good = grep { !($_ ~~ @badvalues ) } @values;

或者为了更清晰的优先级:

my @final_good = grep { not $_ ~~ @badvalues } @values;

这是使用在 Perl 5.10 中添加的 smartmatch 运算符。

【讨论】:

  • 我希望我使用的 Perl 是现代的,我在 5.6.1 上 :( 谢谢你的提示,我会记住的。
  • @Interwebs - 我会为你感到难过,但我们的一些东西仍然停留在 5.005。真丢脸!
【解决方案3】:

DVK's answer 中显示的方法的速度更快且内存消耗更少的版本

my %badvalues;
@badvalues{@badvalues} = ();
my @goodvalues = grep !exists $badvalues{$_}, @values;

【讨论】:

  • 我怀疑世界上是否存在代码,除了少数病态情况外,进行上述优化会显着有益。但是,它会降低可读性。
  • 这段代码从我的第二个示例中获取哈希生成器,然后从我的第一个示例中获取哈希使用:)。当然,这仍然是一个有效的代码——这条评论是我为什么不包括这个解决方案的借口;而不是对你的批评:)
  • @szbalint:您可能会感到惊讶,但编写这样的代码是有实际原因的。编写这种 perl 代码更容易获得 38% 的性能提升和 38% 的内存占用,而不是在 XS 模块中编写可读性更低的 C 代码。这几乎五分之二的速度可能是实际项目中可用和不可用之间的差异。如果你比较 my %badvalues = map {$_=>1} @badvalues;my %badvalues; @badvalues{@badvalues} = (); 可读性并没有太大差异。
  • @szbalint:取决于读者。如果您熟悉该成语,则阅读 empty-assignment-to-hash-slice 比阅读 map 更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 2013-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多