在Perl中,grep
和map
都使用表达式和列表,并为列表中的每个元素计算表达式。
两者有什么区别?
答案 0 :(得分:25)
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,具体取决于相应元素是否为奇数。
答案 1 :(得分:10)
我发现以最常见的形式思考grep()
和map()
是有帮助的:
grep {BLOCK} LIST
map {BLOCK} LIST
grep()
是一个过滤器:它返回LIST中BLOCK返回true的项子集。
map()
是一个映射函数:将一个值从LIST发送到BLOCK,BLOCK返回一个包含0个或更多值的列表;所有这些BLOCK调用的组合集将是map()
返回的最终列表。
答案 2 :(得分: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()
答案 3 :(得分: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
来做这件事就很方便了。
答案 4 :(得分:2)
将grep视为带过滤器的地图。 map迭代并提供对每个项目执行某些操作的机会。例如,这两行是等价的:
my @copy = @original;
my @copy = map {$_} @original;
同样,这两者是等价的:
my @copy = grep {-f $_} @original;
@copy = ();
for (@original)
{
push @copy, $_ if -f $_;
}
grep提供插入条件的功能,因此成为过滤器。
答案 5 :(得分:0)
面对面:grep给出了它的块标量上下文,map给出了它的块列表上下文。 (并且BLOCK foreach LIST给出了它的块无效上下文。)