14

在 Perl 中,grepand都map接受一个表达式和一个列表,并为列表中的每个元素计算表达式。

两者有什么区别?

4

6 回答 6

26

grep返回原始列表中与表达式匹配的元素,同时map返回应用于原始列表每个元素的表达式的结果。

$ perl -le 'print join " ", grep $_ & 1, (1, 2, 3, 4, 5)'
1 3 5
$ perl -le 'print join " ", map $_ & 1, (1, 2, 3, 4, 5)'
1 0 1 0 1

第一个示例打印列表的所有奇数元素,而第二个示例根据相应元素是否为奇数打印 0 或 1。

于 2009-02-22T19:12:32.220 回答
10

我发现以最一般的形式思考grep()和思考是有帮助的:map()

grep {BLOCK} LIST   
map  {BLOCK} LIST

grep()是一个过滤器:它返回 LIST 中 BLOCK 返回 true 的项目子集。

map()是一个映射函数:将一个值从 LIST 发送到 BLOCK,BLOCK 返回一个包含 0 个或多个值的列表;所有这些对 BLOCK 的调用的组合集将是返回的最终列表map()

于 2009-02-22T23:16:59.480 回答
4

map将函数应用于列表中的所有元素并返回结果。

grep返回列表中的所有元素,当函数应用于它们时,它们的计算结果为 true。

my %fruits = (
  banana => {
    color => 'yellow',
    price => 0.79,
    grams => 200
  },
  cherry => {
    color => 'red',
    price => 0.02,
    grams => 10
  },
  orange => {
    color => 'orange',
    price => 1.00,
    grams => 225
  }
);

my %red_fruits = map { $_ => $fruits{$_} }
                   grep { $fruits{$_}->{color} eq 'red' }
                     keys(%fruits);

my @prices = map { $fruits{$_}->{price} } keys(%fruits);
my @colors = map { $fruits{$_}->{color} } keys(%fruits);
my @grams  = map { $fruits{$_}->{grams} } keys(%fruits);

# Print each fruit's name sorted by price lowest to highest:
foreach( sort { $fruits{$a}->{price} <=> $fruits{$b}->{price}} keys(%fruits) )
{
  print "$_ costs $fruits{$_}->{price} each\n";
}# end foreach()
于 2009-02-26T00:32:56.310 回答
3

关于 的另一件事grep:在标量上下文中,它告诉您找到了多少项目。如果您真的不想要第二个列表,但您确实想知道有多少特定种类的项目,这可能很有用。

my @numbers = qw/1 2 3 4 5 6/;

my @odd_numbers  = grep { $_ & 1 } @numbers; # grep returns (1, 3, 5)

my $how_many_odd = grep { $_ & 1 } @numbers; # grep returns 3

编辑:由于 OP 在评论中询问,我应该说您可以map以相同的方式在标量上下文中使用。关键不是这grep两个中唯一一个可以做到这一点,而是有时用grep.

于 2009-02-22T20:24:38.817 回答
2

将 grep 视为带有过滤器的映射。map 迭代并提供对每个项目做某事的机会。例如这两行是等价的:

my @copy = @original;
my @copy = map {$_} @original;

同样,这两个是等价的:

my @copy = grep {-f $_} @original;

@copy = ();
for (@original)
{
  push @copy, $_ if -f $_;
}

grep 提供插入条件的能力,因此成为过滤器。

于 2009-02-22T20:05:20.237 回答
0

开玩笑:grep 给出它的块标量上下文,map 给出它的块列表上下文。(并且 BLOCK foreach LIST 给出了它的块无效上下文。)

于 2011-05-19T08:04:58.000 回答