我可以将这个Perl组合到一个map-grep链中吗?

时间:2013-11-14 17:28:35

标签: perl map foreach grep

我可以将这个Perl组合到一个map-grep链中吗? 一个小小的声音说我应该能够,但我不知道怎么做!

# expand sponsor keys in to a list of sponsor objects.
foreach my $event (@events) {
  next unless exists $event->{sponsors} && ! ref $event->{sponsors};
  $event->{sponsors} =
    [ map { $lookup{$_} }
        grep { exists $lookup{$_} }
          split( /\s*,\s*/, $event->{sponsors} ) ];
}

3 个答案:

答案 0 :(得分:3)

我是(可读)map-grep链的忠实粉丝。尽管如此,虽然我知道 map越来越多地处理在void上下文中使用的更好,我不喜欢使用 在void上下文中 map 。除此之外,我更喜欢哈希切片来填充内容 数组。如果查找的值不是undef,那么请点击全部 哈希切片中定义的值应该与grep一样有效 那些exist然后将它们转换为查找值。

所以我提供了这个map解决方案:

map { 
    $_->{sponsors}
        = [ grep {; defined } @lookup{ split( /\s*,\s*/, $_->{sponsors} ) } ]
        ;
}
grep { $_->{sponsors} && !ref $_->{sponsors} }  @events
;

此处使用map的问题在于,您不是要从另一个项目创建一个项目列表。您正在更新一个列表。

就我的偏好而言,你也可以轻松地做一个fore-foreach:

 do { 
    $_->{sponsors}
        = [ grep {; defined } @lookup{ split( /\s*,\s*/, $_->{sponsors} ) } ]
        ;
 }
 foreach { $_->{sponsors} && !ref $_->{sponsors} }  @events
;

但这与你原来的并没有什么不同。你可以轻松地把那个foreach放在顶部。但然后你有一个循环,我也没有next的问题。我认为可以获得的最大收益是使用散列片而不是grepping并映射到相同的值。

答案 1 :(得分:1)

就我个人而言,我认为简单的foreach比使用map / grep更具可读性:

foreach my $event (@events) {
    next unless exists $event->{sponsors} && ! ref $event->{sponsors};

    my @sponsors;
    foreach my $sponsor ( split /\s*,\s*/, $event->{sponsors} ) {
        push @sponsors, $sponsor if exists $lookup{$sponsor};
    }

    $event->{sponsors} = [ @sponsors ];
}

答案 2 :(得分:0)

没有尝试过,但它应该是:

 my $event;
 push( @{ $event->{sponsors} }, 
         map { $lookup{$_} }
           grep { $lookup{$_} }
             split( /\s*,\s*/, $event->{sponsors} ) 
               grep { $_->{sponsors} && $event = $_ } @events);