如何使用map将一个函数应用于列表?

11

我想对列表的每个元素应用一个函数并将结果存储,类似于Python中的 map(function, list)

尝试使用map函数并传递一个函数,但是出现了以下错误:

perl -le 'my $s = sub {}; @r = map $s 0..9'
panic: ck_grep at -e line 1.

这该怎么做才是正确的?

4个回答

9
如果一个标量变量保存了代码引用,例如:
my $double = sub { 2 * shift };

您可以像在Python中一样调用代码,如下所示:

$double->(50);  # Returns 100.

将其应用于一个map示例:
my @doubles = map $double->($_), 1..10;

或者这样:
my @doubles = map { $double->($_) } 1..10;

第二种变体更加健壮,因为由 {} 花括号定义的块可以包含任意数量的 Perl 语句:
my @doubles = map {
    my $result = 2 * $_;

    # Other computations, if needed.

    $result;  # The return of each call to the map block.
} 1..10;

1
不错的回答,还要注意在 map 块中,与大多数其他块不同,您不能安装词法 pragma 或执行其他编译时操作(use .../no ...)。 - Eric Strom
map BLOCK LIST形式的map中可以使用useno,但在map EXPR LIST形式中不能使用。只是如果你使用它们,您可能需要使用前导;来区分块和表达式。或者,您可以将do BLOCK用作表达式,它可以包含nouse。 use strict; my @a = 1..10; my @b = map {; no strict 'vars'; $x = $_ + 1; $x } @a; my @c = map { do { no strict 'vars'; $x = $_+ 1; $x} } @a; - MkV
值得注意的是,循环中的 $_ 是数组元素的别名,因此修改它会修改源数组,这不利于清晰的代码。 - MkV

5

尝试使用 map { $s->($_) } (0..9) 替代 map $s 0..9

解释:在你的例子中,$s 是一个子程序的引用,因此必须对其进行解引用以允许调用子程序。这可以通过多种方式实现:$s->()&$s()(还有可能我忘记的其他方式)。


5
  my $squared = sub {
        my $arg = shift();
        return $arg ** 2;
  };

那么,要么
   my @list = map { &$squared($_)  } 0 .. 12;

或者

   my @list = map { $squared->($_) } 0 .. 12;

或者也许

my $squared;
BEGIN {
    *Squared = $squared = sub(_) {
        my $arg = shift();
        return $arg ** 2;
    };
}
my @list = map { Squared } 0 .. 12;

2

这与Python并没有太大的不同。

@results = map { function($_) } @list;
@results = map function($_), @list;

或者使用“lambda”函数,
@results = map { $function->($_) } @list;
@results = map $function->($_), @list;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接