14
A
回答
24
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根据相应元件是奇数还是不行。
2
将grep想象成带有过滤器的映射。地图迭代,并提供了一个机会来处理每个项目。例如,这些两行是等效的:
my @copy = @original;
my @copy = map {$_} @original;
类似地,这两个是相同的:
my @copy = grep {-f $_} @original;
@copy =();
for (@original)
{
push @copy, $_ if -f $_;
}
的grep提供到插入条件的能力,并因此成为一个过滤器。
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
来实现。
10
我发现它的认为想在他们最普遍的形式约grep()
和map()
有所帮助:
grep {BLOCK} LIST
map {BLOCK} LIST
grep()
是一个过滤器:它返回从列表中哪些块返回true项目的子集。
map()
是一个映射函数:将LIST中的值发送到BLOCK,BLOCK返回0或更多值的列表;所有这些BLOCK呼叫的组合将是由map()
返回的最终列表。
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()
0
草率地说:grep给出了它的块标量上下文,map给出了它的块列表上下文。 (并且BLOCK foreach LIST给出了它的块空白上下文。)
此外,map允许一对多映射,所以它的表达式在列表上下文中,而不是grep表达式的标量上下文。 – ysth 2009-02-22 20:10:05
@ysth:的确如此。我打算说一些关于map总是返回与列表参数相同数量的元素,但后来记住表达式可以返回一个或多个元素作为列表。 – 2009-02-22 20:57:04