Perl中的Ruby 'reject!`等价物?

iyfamqjs  于 2022-11-04  发布在  Ruby
关注(0)|答案(3)|浏览(186)

我需要遍历一个数组,并有条件地删除元素,在Perl中。我知道slice,但不确定如何在foreach上下文中使用它。
在Ruby中,有reject!

foo = [2, 3, 6, 7]
foo.reject! { |x| x > 3 }
p foo   # outputs "[2, 3]"

有没有Perl的对等用法?

fivyi3re

fivyi3re1#

您可以使用Perl的grep,它的作用类似于反向拒绝:它将保留所有满足条件的项。因此reject x > 3必须变为grep x <= 3

@foo = (2, 3, 6, 7);
@foo = grep { $_ <= 3 } @foo;
print @foo; # 23

条件不一定是数值比较,但可以是在布尔上下文中工作的任何内容,例如,与正则表达式匹配。

gzszwxb4

gzszwxb42#

正如其他答案所示,grep通常就是您所需要的全部。
然而,使用perl原型可以编写一个函数,像ruby的Array#reject!

    • 接受块 *
    • 可以在适当的位置修改其参数数组 *

用法为:

@foo = (2, 3, 6, 7);            # Void context - modify @foo in place
reject { $_ > 3 } @foo;         # @foo is now (2, 3)

@foo = (2, 3, 6, 7);            # Scalar context - modify @foo in place
$n = reject { $_ > 3 } @foo;    # @foo is now (2, 3), $n is length of modified @foo

@foo = (2, 3, 6, 7);            # Array context - return a modified copy of @foo
@cpy = reject { $_ > 3 } @foo;  # @cpy is (2, 3), @foo is (2, 3, 6, 7)

实施:

sub reject(&\@) {
    my ($block, $ary) = @_;

    # Return a copy in an array context
    return grep {! $block->() } @$ary if wantarray;

    # Otherwise modify in place.  Similar to, but not
    # quite, how rb_ary_reject_bang() does it.
    my $i = 0;
    for (@$ary) {
            next if $block->();
            ($ary->[$i], $_) = ($_, $ary->[$i]); # swap idiom to avoid copying
            $i++;                                # possibly huge scalar
    }
    $#$ary = $i - 1;  # Shorten the input array

    # We differ from Array#reject! in that we return the number of
    # elements in the modified array, rather than an undef value if
    # no rejections were made
    return scalar(@$ary) if defined(wantarray);
}
iyzzxitl

iyzzxitl3#

vinko@parrot:/home/vinko# more reject.pl
my @numbers = (2, 3, 6 ,7);
print join(",", grep { $_ <= 3 } @numbers)."\n";

vinko@parrot:/home/vinko# perl reject.pl
2,3

相关问题