2009-02-22 149 views

回答

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根据相应元件是奇数还是不行。

+1

此外,map允许一对多映射,所以它的表达式在列表上下文中,而不是grep表达式的标量上下文。 – ysth 2009-02-22 20:10:05

+0

@ysth:的确如此。我打算说一些关于map总是返回与列表参数相同数量的元素,但后来记住表达式可以返回一个或多个元素作为列表。 – 2009-02-22 20:57:04

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给出了它的块空白上下文。)