2011-07-15 234 views
5

有没有一种快速简单的方法来通过数组找到满足某些测试的元素从原始数组中删除这些元素?我怎样才能通过数组grep,而过滤出匹配?

例如我想

@a = (1, 7, 6, 3, 8, 4); 
@b = grep_filter { $_ > 5 } @a; 

# now @b = (7, 6, 8) 
# and @a = (1, 3, 4) 

换句话说,我想要的阵列分成两个阵列:那些匹配这和那些不符合特定条件。

+0

为什么呢?它很容易阅读,从@a('foreach(@a){if($ _> 5){push @b,$ _;} else {push @c,$ _;}}创建2个数组。 ')为什么你需要做到这一点“部分到位”? – mirod

+0

,因为我很懒。 –

回答

9

知道你的图书馆,芒。

use List::MoreUtils qw(part); 
part { $_>5 } (1, 7, 6, 3, 8, 4) 

回报

(
    [1, 3, 4], 
    [7, 6, 8], 
) 
+0

不错,几乎是我在找的东西。 –

-1

这是你想要的吗?

@a = (1, 7, 6, 3, 8, 4); 
@b = grep_filter { $_ > 5 } @a; 
@a = grep_filter { $_ < 5 } @a; 

做另一个grep与您的条件否定。

+1

'<'不是'>'的严格否定。 – Alnitak

+0

@Alnitak - 你是对的,我没有提到过,但我把'<'而不是'<='为了使代码正常工作 –

+0

@Tudor:为什么逻辑错误使代码工作为预计,而不是正确的<=? – pavel

8
my @a = (1, 7, 6, 3, 8, 4); 
my (@b, @c);  

push @{ $_ > 5 ? \@b : \@c }, $_ for @a; 
+0

+1,因为这是一个不需要任何外部库的很好的解决方案。 –

3

使用库是好的,但为了完整起见,这里是在问题中指定的功能:

sub grep_filter (&\@) { 
    my ($code, $src) = @_; 
    my ($i, @ret) = 0; 
    local *_; 
    while ($i < @$src) { 
     *_ = \$$src[$i]; 
     &$code 
      ? push @ret, splice @$src, $i, 1 
      : $i++ 
    } 
    @ret 
} 

my @a = (1, 7, 6, 3, 8, 4); 
my @b = grep_filter {$_ > 5} @a; 

say "@a"; # 1 3 4 
say "@b"; # 7 6 8