Ada*_*ire 44
任何时候您想要基于另一个列表生成列表:
# Double all elements of a list
my @double = map { $_ * 2 } (1,2,3,4,5);
# @double = (2,4,6,8,10);
Run Code Online (Sandbox Code Playgroud)
由于列表很容易成对转换为哈希值,因此如果您需要基于特定属性的对象哈希表:
# @user_objects is a list of objects having a unique_id() method
my %users = map { $_->unique_id() => $_ } @user_objects;
# %users = ( $id => $obj, $id => $obj, ...);
Run Code Online (Sandbox Code Playgroud)
它是一个非常通用的工具,您必须开始使用它来在您的应用程序中找到好的用途.
为了便于阅读,有些人可能更喜欢详细的循环代码,但就个人而言,我发现它map更具可读性.
Sam*_*ton 29
首先,它是一种转换数组的简单方法:而不是说例如
my @raw_values = (...);
my @derived_values;
for my $value (@raw_values) {
push (@derived_values, _derived_value($value));
}
Run Code Online (Sandbox Code Playgroud)
你可以说
my @raw_values = (...);
my @derived_values = map { _derived_value($_) } @raw_values;
Run Code Online (Sandbox Code Playgroud)
它对于构建快速查找表也很有用:而不是例如
my $sentence = "...";
my @stopwords = (...);
my @foundstopwords;
for my $word (split(/\s+/, $sentence)) {
for my $stopword (@stopwords) {
if ($word eq $stopword) {
push (@foundstopwords, $word);
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以说
my $sentence = "...";
my @stopwords = (...);
my %is_stopword = map { $_ => 1 } @stopwords;
my @foundstopwords = grep { $is_stopword{$_} } split(/\s+/, $sentence);
Run Code Online (Sandbox Code Playgroud)
如果你想从另一个列表中导出一个列表,它也很有用,但不要特别需要让一个临时变量混乱,例如而不是
my %params = ( username => '...', password => '...', action => $action );
my @parampairs;
for my $param (keys %params) {
push (@parampairs, $param . '=' . CGI::escape($params{$param}));
}
my $url = $ENV{SCRIPT_NAME} . '?' . join('&', @parampairs);
Run Code Online (Sandbox Code Playgroud)
你说的更简单
my %params = ( username => '...', password => '...', action => $action );
my $url = $ENV{SCRIPT_NAME} . '?'
. join('&', map { $_ . '=' . CGI::escape($params{$_}) } keys %params);
Run Code Online (Sandbox Code Playgroud)
(编辑:修复了最后一行中缺少的"键%params")
Mic*_*man 21
该map函数用于转换列表.它基本上是用于替换某些类型的for[each]循环的语法糖.一旦你绕过它,你就会看到它的用处:
my @uppercase = map { uc } @lowercase;
my @hex = map { sprintf "0x%x", $_ } @decimal;
my %hash = map { $_ => 1 } @array;
sub join_csv { join(',', map {'"' . $_ . '"' } @_ }
Run Code Online (Sandbox Code Playgroud)
cjm*_*cjm 12
它对于查找哈希也很方便:
my %is_boolean = map { $_ => 1 } qw(true false);
Run Code Online (Sandbox Code Playgroud)
相当于
my %is_boolean = ( true => 1, false => 1 );
Run Code Online (Sandbox Code Playgroud)
那里没有多少积蓄,但假设你想定义%is_US_state?
kix*_*ixx 11
map用于通过转换另一个列表的元素来创建列表.
grep用于通过过滤另一个列表的元素来创建列表.
sort用于通过对另一个列表的元素进行排序来创建列表.
这些运算符中的每一个都接收代码块(或表达式),用于转换,过滤或比较列表的元素.
对于map,块的结果将成为新列表中的一个(或多个)元素.当前元素别名为$ _.
对于grep,块的布尔结果决定是否将原始列表的元素复制到新列表中.当前元素别名为$ _.
对于sort,块接收两个元素(别名为$ a和$ b),并且预期返回-1,0或1中的一个,指示$ a是大于,等于还是小于$ b.
所述的Schwartzian变换使用这些运营商能够有效的缓存值(属性),以在一个分拣列表中使用,尤其是当计算这些性能具有一个非平凡成本.
它的工作原理是创建一个中间数组,该数组具有作为元素数组引用的原始元素和我们想要排序的计算值.这个数组被传递给sort,它比较已经计算好的值,创建另一个中间数组(这个被排序),然后传递给另一个抛出缓存值的map,从而将数组恢复到它的初始列表元素(但是现在按照所需的顺序).
示例(创建当前目录中按上次修改时间排序的文件列表):
@file_list = glob('*');
@file_modify_times = map { [ $_, (stat($_))[8] ] } @file_list;
@files_sorted_by_mtime = sort { $a->[1] <=> $b->[1] } @file_modify_times;
@sorted_files = map { $_->[0] } @files_sorted_by_mtime;
Run Code Online (Sandbox Code Playgroud)
通过将运算符链接在一起,中间数组不需要声明变量;
@sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, (stat($_))[8] ] } glob('*');
Run Code Online (Sandbox Code Playgroud)
您还可以在排序之前通过插入grep来过滤列表(如果要对相同的缓存值进行过滤):
示例(过去24小时内修改的文件列表,对最后修改时间进行了排序):
@sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } grep { $_->[1] > (time - 24 * 3600 } map { [ $_, (stat($_))[8] ] } glob('*');
Run Code Online (Sandbox Code Playgroud)
map函数在列表的每个元素上运行一个表达式,并返回列表结果.可以说我有以下列表
@names = ("andrew", "bob", "carol" );
Run Code Online (Sandbox Code Playgroud)
我想把这些名字的第一个字母大写.我可以遍历它们并调用每个元素的ucfirst,或者我可以执行以下操作
@names = map (ucfirst, @names);
Run Code Online (Sandbox Code Playgroud)
map函数是函数式编程范例的一个概念.在函数式编程中,函数是第一类对象,这意味着它们可以作为参数传递给其他函数.地图是一个简单但非常有用的例子.它将一个函数(让我们称之为f)和一个列表作为其参数l. f必须是一个带有一个参数的函数,map只适用f于列表的每个元素l. f可以对每个元素执行任何操作:向每个元素添加一个元素,为每个元素添加方块,将每个元素写入数据库,或者为每个元素打开Web浏览器窗口,这恰好是一个有效的URL.
使用的优点map是它很好地封装了迭代列表的元素.你所要做的就是说" f对每一个元素都做,并且map决定如何最好地做到这一点.例如map可以实现在多个线程之间分割它的工作,并且它对调用者来说是完全透明的.
注意,这map完全不是Perl特有的.它是功能语言使用的标准技术.它甚至可以使用函数指针在C中实现,或者在使用"函数对象"的C++中实现.
"只是糖"是苛刻的.记住,循环只是糖 - 如果和goto可以做所有循环结构做的事情.
Map是一个足够高级别的功能,它可以帮助您在头脑中执行更复杂的操作,因此您可以编写和调试更大的问题.