Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 什么';这就是Perl';s地图?_List_Perl_Dictionary_Higher Order Functions - Fatal编程技术网

List 什么';这就是Perl';s地图?

List 什么';这就是Perl';s地图?,list,perl,dictionary,higher-order-functions,List,Perl,Dictionary,Higher Order Functions,没有真正理解map函数的意义。有人能举例说明它的用途吗 使用它而不是循环有什么性能优势吗?或者它只是糖吗?任何时候您都可以基于另一个列表生成列表: # Double all elements of a list my @double = map { $_ * 2 } (1,2,3,4,5); # @double = (2,4,6,8,10); 由于列表很容易两两转换为散列,因此如果需要基于特定属性的对象的散列表: # @user_objects is a list of objects hav

没有真正理解map函数的意义。有人能举例说明它的用途吗


使用它而不是循环有什么性能优势吗?或者它只是糖吗?

任何时候您都可以基于另一个列表生成列表:

# Double all elements of a list
my @double = map { $_ * 2 } (1,2,3,4,5);
# @double = (2,4,6,8,10);
由于列表很容易两两转换为散列,因此如果需要基于特定属性的对象的散列表:

# @user_objects is a list of objects having a unique_id() method
my %users = map { $_->unique_id() => $_ } @user_objects;
# %users = ( $id => $obj, $id => $obj, ...);
它是一个真正通用的工具,您必须开始使用它才能在应用程序中找到好的用途


出于可读性的目的,有些人可能更喜欢详细的循环代码,但就我个人而言,我发现
map
更可读。

map函数在列表的每个元素上运行一个表达式,并返回列表结果。假设我有以下清单

@names = ("andrew", "bob", "carol" );
我想把每个名字的第一个字母大写。我可以循环遍历它们并调用每个元素的第一个元素,或者我可以执行以下操作

@names = map (ucfirst, @names);

它可以在您希望从现有列表创建新列表的任何时候使用

例如,您可以将解析函数映射到字符串列表上,以将其转换为整数。

要理解Hall&Schwartz的“高效Perl编程”一词, map可能被滥用,但我认为最好使用它从现有列表创建一个新列表

创建3、2和1的正方形列表:

@numbers = (3,2,1);
@squares = map { $_ ** 2 } @numbers;

另请参见地图的高级用法。

它还可以方便地进行查找哈希:

my %is_boolean = map { $_ => 1 } qw(true false);
相当于

my %is_boolean = ( true => 1, false => 1 );
这里节省的钱不多,但假设您想定义
%是否为\u US\u state

生成密码:

$ perl -E'say map {chr(32 + 95 * rand)} 1..16'
# -> j'k=$^o7\l'yi28G

map
函数用于转换列表。它基本上是为[每个]循环替换某些类型的
。一旦你把头绕到它身上,你就会在任何地方看到它的用途:

my @uppercase = map { uc } @lowercase;
my @hex       = map { sprintf "0x%x", $_ } @decimal;
my %hash      = map { $_ => 1 } @array;
sub join_csv { join ',', map {'"' . $_ . '"' } @_ }

首先,这是一种转换数组的简单方法:而不是说

my @raw_values = (...);
my @derived_values;
for my $value (@raw_values) {
    push (@derived_values, _derived_value($value));
}
你可以说

my @raw_values = (...);
my @derived_values = map { _derived_value($_) } @raw_values;
它对于建立快速查找表也很有用:而不是例如

my $sentence = "...";
my @stopwords = (...);
my @foundstopwords;
for my $word (split(/\s+/, $sentence)) {
    for my $stopword (@stopwords) {
       if ($word eq $stopword) {
           push (@foundstopwords, $word);
       }
    }
}
你可以说

my $sentence = "...";
my @stopwords = (...);
my %is_stopword = map { $_ => 1 } @stopwords;
my @foundstopwords = grep { $is_stopword{$_} } split(/\s+/, $sentence);
如果您希望从一个列表中派生另一个列表,但不需要临时变量将位置弄乱,例如,而不是

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);
你说的更简单

my %params = ( username => '...', password => '...', action => $action );
my $url = $ENV{SCRIPT_NAME} . '?'
    . join('&', map { $_ . '=' . CGI::escape($params{$_}) } keys %params);

(编辑:修复了最后一行中缺少的“keys%params”)

使用map转换列表并将结果分配给另一个列表,使用grep筛选列表并将结果分配给另一个列表。“其他”列表可以是与正在转换/筛选的列表相同的变量

my @array = ( 1..5 );
@array = map { $_+5 } @array;
print "@array\n";
@array = grep { $_ < 7 } @array;
print "@array\n";
my@array=(1..5);
@array=map{$\u5}@array;
打印“@array\n”;
@array=grep{$\u7}@array;
打印“@array\n”;

它允许您将列表转换为表达式而不是语句。想象一堆士兵的定义如下:

{ name          => 'John Smith'
, rank          => 'Lieutenant'
, serial_number => '382-293937-20'
};
然后,您可以分别对名称列表进行操作

比如说,

map { $_->{name} } values %soldiers
这是一个表达。它可以放在表达式允许的任何地方——除非您不能为它赋值

${[ sort map { $_->{name} } values %soldiers ]}[-1]
索引数组,取最大值

my %soldiers_by_sn = map { $->{serial_number} => $_ } values %soldiers;
我发现运算表达式的优点之一是它减少了来自临时变量的bug

如果McCoy先生想过滤掉所有的hatfield以供考虑,你可以用最少的编码添加检查

my %soldiers_by_sn 
    = map  { $->{serial_number}, $_ } 
      grep { $_->{name} !~ m/Hatfield$/ } 
      values %soldiers
      ;

我可以继续链接这些表达式,这样,如果我与这些数据的交互必须深入到某个特定目的,我就不必编写太多假装我要做更多的代码

map函数是函数式编程范式的一个思想。在函数式编程中,函数是一级对象,这意味着它们可以作为参数传递给其他函数。Map是一个简单但非常有用的例子。它的参数是一个函数(我们称它为
f
)和一个列表
l
f
必须是一个带一个参数的函数,map只将
f
应用于列表的每个元素
l
f
可以对每个元素执行您需要执行的任何操作:为每个元素添加一个元素、对每个元素进行平方运算、将每个元素写入数据库,或者为每个元素打开一个web浏览器窗口,这恰好是一个有效的URL

使用
map
的优点是它很好地封装了对列表元素的迭代。您所要做的就是对每个元素说“do
f
,这取决于
map
来决定如何最好地做到这一点。例如,
map
可以实现为在多个线程之间分割其工作,并且对调用方完全透明


<> >注意,<>代码> map > />代码并不完全是Perl。它是函数语言使用的标准技术。它甚至可以用函数指针在C中实现,或者在C++中使用“函数对象”。

< P>>强> map < /St>用于通过转换另一个列表的元素来创建列表。 grep用于通过过滤另一个列表的元素来创建列表

排序用于通过对另一个列表的元素进行排序来创建列表

这些运算符中的每一个都接收一个代码块(或表达式),用于转换、过滤或比较列表中的元素

对于map,块的结果成为新列表中的一个(或多个)元素。当前元素的别名为$

对于grep,块的布尔结果决定是否将原始列表的元素复制到新列表中。当前元素的别名为$

对于排序,块接收两个元素(别名为$a和$b),并预期返回-1、0或1中的一个,指示$a是大于、等于还是小于$b

使用这些运算符可以高效地缓存要在列表排序中使用的值(属性),尤其是当计算这些属性的成本非常大时

它通过创建一个中间ar来工作
@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;
@sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, (stat($_))[8] ] } glob('*');
    @sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } grep { $_->[1] > (time - 24 * 3600 } map { [ $_, (stat($_))[8] ] } glob('*');
my @patents = ('7,120,721', '6,809,505', '7,194,673');
print join(", ", map { "<a href=\"http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL&p=1&u=/netahtml/srchnum.htm&r=0&f=S&l=50&TERM1=$_\">$_</a>" } @patents);
perl -e '@x=("x"); map { push @x, $_ } @x'
perl -e '@x=("x"); push @x, $_ for @x'