【问题标题】:Perl splitting array based on condition using grepPerl使用grep根据条件拆分数组
【发布时间】:2012-01-26 22:08:13
【问题描述】:

我有一些看起来像这样的 perl 代码:

my @array = map { rand } ( 1..100 );
my @matching = grep { $_ == $condition } @array;
@array = grep { $_ != $condition } @array;

这工作正常,但我想做的是基于单个操作将原始数组分成两个...我认为我执行的操作是严格必要的两倍。

帮助表示赞赏!谢谢。

【问题讨论】:

    标签: arrays perl grep


    【解决方案1】:

    这就是List::MoreUtils 中的part 派上用场的地方。

    use List::MoreUtils qw'part';
    my($even,$odd) = part { $_ % 2 } @array;
    

    如果您希望输入的每个元素恰好位于输出的一个数组中,这将非常有用。


    如果您想将它们放入多个数组中,则必须自己循环遍历它们。
    最好的方法是使用foreach 循环。

    my(@div2,@div3);
    for my $elem (@array){
      push @div2, $elem unless $elem % 2;
      push @div3, $elem unless $elem % 3;
    }
    

    如果您必须做很多类似的检查,也许您也应该循环检查您的测试对象。

    my %div;
    for my $elem (@array){
      for my $div (2,3,5,7,11,13){
        push @{ $out{$div} }, $elem unless $elem % $div;
      }
    }
    

    【讨论】:

    • 我喜欢 part 的 PP 实现中使用的索引技巧
    【解决方案2】:

    到目前为止,最简单的方法是迭代您的数组并根据条件将值推送到两个数组中的任何一个,如下例所示。

    for (@array) {
      if ($_ % 2) {push @odd,  $_}
      else        {push @even, $_}
    }
    

    如果你想修改源数组:

    for (my $i =0; $i < @array; ++$i) {
      if ($array[$i] % 2) {
        push @odd, splice (@array, $i--, 1);
      }
    }
    

    为什么不推荐 List::MoreUtils::part?

    有问题的模块可能不存在于目标系统上,这总是一件烦人的事情。

    在我运行测试的系统上,我发现List::MoreUtils::part 的速度是本文中第一个 sn-p 的两倍,尽管 part 的不同实现实际上可能相反。 em>

    【讨论】:

    • List::MoreUtils not existing: Yes, even you can use CPAN -- 基准测试听起来像是过早的优化。读起来像它的规范的代码总是更好,直到你知道你需要更快的东西,即使那样,那时也可能会进行不同的优化(例如,XS?)
    • 我的测试显示,当 XS(快 169% - 远超过两倍)时,部分速度明显更快,但当 PP(-52%,略低于一半)w/perl 5.14.2 时,速度较慢- 相当合理的价格。 @array 越大,part 的性能就越好。
    • @Tanktalus 是的,当使用 PP 时,定制功能更快,尽管与 XS 相比它没有机会。至于 cpan,当然你可以通过cpan 安装它,但是因为一个功能而安装一个完整的模块就过分了,至少如果你问我的话。
    • Modules that depend on List::MoreUtils 包括 Ubic Perl-Critic Moose Padre PPI 如果你真的使用 Perl 来完成工作,你可能已经安装了其中之一,所以列出::已经安装了 MoreUtils。
    • @BradGilbert 如果你真的使用 perl 来快速完成工作,而不是总是在你自己的机器上执行它。很有可能它不存在。
    【解决方案3】:

    我喜欢List::MoreUtils'part 函数的简单性:

    sub part (&@) {
        my ($code, @list) = @_;
        my @parts;
        push @{ $parts[ $code->($_) ] }, $_  foreach @list;
        return @parts;
    }
    

    生成的@parts 数组是一个arrayrefs 数组。 @$parts[0] 是返回 false 的元素数组。 @$parts[1] 返回 true。

    【讨论】:

    • 我认为可以添加一件事。如果 code-ref 的返回值可以是一个数组。然后您可以将每个元素放入多个输出数组中。
    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多