perl的map函数
转自:http://hi.baidu.com/tkocn/blog/item/3b3e61df47e75b1049540394.html
对perl的map函数用的总是不好,今天看了perlChina的一篇文章,有所体会,在此收藏:
翻 译:zjl_perl The map function map函数 map BLOCK LIST map EXPR,LIST
The map function evaluates the BLOCK or EXPR for each element of LIST,locally setting the $_ variable equal to each element. It returns a list of the results of each evaluation. Map evaluates BLOCK or EXPR in a list context. Each element of LIST may produce zero,one,or more elements in the output list. map函数对LIST中的每一个元素都进行一次BLOCK或者EXPR计算。$_代表LIST中当前的元素。map函数返回的列表是由每一次计算所 得到的结果组成。Map运算BLOCK或者EXPR的时候是处于列表上下文的。LIST中的每个元素通过运算,都会得到一个或多个值,或者不生成值。 LIST中所有元素运算完毕后得到的所有值组成结果列表。 In a scalar context,map returns the number of elements in the results. In a hash context,the output list (a,b,c,d,...) is cast into the form ( a => b,c => d,... ). If the number of output list elements is not even,the last hash element will have an undefined value. 在标量上下文中,map返回结果表中元素的个数。在哈希表上下文中,输出的表(a,...)被分组成为哈希表的格式(a=>b,c=>d,...)。如果输出列表中的元素不成对儿,那么最后一个元素作为键将会对应一个undefined值。 Avoid modifying $ in map’s BLOCK or EXPR,as this will modify the elements of LIST. (If you need to modify $ without modifying LIST,use this simple work-around.) Also,avoid using the list returned by map as an lvalue,as this will modify the elements of LIST. (An lvalue is a variable on the left side of an assignment statement.) Some Perl hackers may try to exploit this feature,but I recommend that you avoid this confusing style of programming. 不要在map的BLOCK或者EXPR中修改$_,因为这会改变LIST中元素的值。(如果你想改变$_而不改变LIST,那么就使用这个 。)同样,避免用map函数返回的列表作为等式左值,因为这也会改变LIST中的元素。(左值就是赋值表达式中传递给等号左边的值)也许一些perl骇客们会努力开发这种特性,但我建议你不要使用这种令人迷惑的编程方式。 Map vs. grep vs. foreach Map 对垒 grep 对垒 foreach Map can select elements from an array,just like grep. The following two statements are equivalent: map可以从数组中选取元素,就像grep一样。下面两个表达式效果相同: @selected = grep EXPR,@input; (EXPR represents a logical expression.) Also,map is just a special case of a foreach statement. If the @transformed array is currently undefined or empty,the following two statements are equivalent: (EXPR是一个逻辑表达式)同样,map可以说是foreach语句的一种特殊情况。如果数组@transformed是未定义或者为空,那么下面两个语句是等效的: foreach (@input) { push @transformed,EXPR; } In general,use grep to select elements from an array and map to transform the elements of an array. Other array processing can be done with one of the loop statements (foreach,for,while,until,do while,do until,redo). Avoid using statements in grep/map blocks that do not affect the grep/map results; moving these “side-effect” statements to a loop makes your code more readable and cohesive. 总的来说,使用grep来选取数组中的元素,而用map来转换数组中的元素。其他的数组操作可以用任一种循环语句来实现(foreach,for, while,until,do while,do until,redo)。不要在grep/map的程序块儿中使用不影响grep/map结果的语句;把这些“副作用”语句移入一个循环,这样能让你的代 码可读性更强,结构更好。 Transform filenames to file sizes 利用文件名列表得到文件占用空间列表 @sizes = map { -s $_ } @file_names; The -s file test operator returns the size of a file and will work on regular files,directories,special files,etc. 文件测试符-s返回一个文件占用的空间,可以用于普通的文件、目录和一些特殊文件等等。 Convert an array to a hash: find the index for an array value 将数组转成哈希表:为数组的值添加一个索引 Instead of repeatedly searching an array,we can use map to convert the array to a hash and then do a direct lookup by hash key. The code using map is simpler and,if we are doing repeated searches,more efficient. 为了不想总是重复地搜索数组,我们可以使用map来把数组转为哈希表。然后用哈希表的键来直接查询。这样做会更加简单,比重复的搜索更加有效率。 In this example we use map and a hash to find the array index for a particular value: 在这个例子中我们使用map和一个哈希表来寻找一个特定值在数组中的索引: @teams = qw(Miami Oregon Florida Tennessee Texas The .. is Perl’s range operator and $#teams is the maximum index of the @teams array. When the range operator is bracketed by two numbers,it generates a list of integers for the specified range. “..”是perl的范围操作符$#teams是数组teams的最大索引值。当在两个数字之间加上范围操作符,则生成一个特定范围的整型数列表。 When using map to convert an array to a hash,we need to think about how non-unique array elements affect the hash. In the example above,a non-unique team name will make the code print the lowest rank for that team name. Non-unique team names are probably a data entry error; one way to handle them would be to add a second map to preprocess the array and convert the second and subsequent occurrences of a name to a dummy value (and output an error message). 当用map来将数组转成哈希表的时候,我们需要考虑重复的数组元素对于哈希表的影响。在上面的例子中,重复的队名只会让代码打印出排名最低的那一 个。重复的队名也许是数据录入错误;有一个解决方法是再用一个map来预处理一下数组,把第二个并发出现的名字转换成虚拟的值(并且输出错误信息)。 Convert an array to a hash: search for misspelled words 将数组转成哈希表:搜寻拼写错误的单词 Converting an array to a hash is a fairly common use for map. In this example the values of the hash are irrelevant; we are only checking for the existence of hash keys. 将数组转成哈希表是map的一个普遍应用。在这个例子中,哈希表的值并不重要;我们只检查哈希表的键是否存在。 %dictionary = map { $_,1 } qw(cat dog man woman hat glove); This is more efficient than using the grep function to search the entire dictionary for each word. In contrast to the previous example,duplicate values in the input list do not affect the results. 这比用grep方法为每个词去搜索整个字典要有效率得多。与上面的那个例子对比,输入数组中元素的重复并不影响最终结果。 Convert an array to a hash: store selected CGI parameters 将数组转为哈希表:存储选定的CGI参数 A hash is often the most convenient way to store input parameters to a program or subroutine,and map is often the most convenient way to create the parameter hash. 用哈希表来存储给某个程序或者某个子程序的参数是最常见、最方便的。而map函数就经常用来生成这种参数哈希表。 use CGI qw(param); The param() call returns a list of CGI parameter names; the param($) call returns the CGI parameter value for a name. If the param($) call returns multiple values for a CGI parameter,the ( param($_) )[0] syntax extracts only the first value so that the hash is still well-defined. Map’s block could be modified to issue a warning message for multi-valued parameters. param()返回一个CGI参数名称的列表;param($)返回特定名字的CGI参数值。如果param($)返回的CGI参数值是多值的话,pram($_)[0]只提取第一个参数值,那么哈希表还是可以成功构建的。map的程序块儿也可以修改成当遇到多值参数的情况时给出一个警告信息。 Generate a random password 生成一个随机密码 In this example the values of the elements in map’s input LIST are irrelevant; only the number of elements in LIST affects the result. 在这个例子中map的输入列表LIST的值并不重要;只有LIST中元素的数量影响最终结果。 @a = (0 .. 9,'a' .. 'z'); (You would have to augment this example for production use,as most computer systems require a letter for the first character of a password.) (你也许在正式使用这个例子之前扩展一下这个例子,因为大多数计算机系统要求密码的第一个字符是字母。) Strip digits from the elements of an array 将数组元素中的数字去掉 As with grep,avoid modifying $_ in map’s block or using the returned list value as an lvalue,as this will modify the elements of LIST. 和用grep一样,不要在map的程序块儿中修改$_值,或者将返回的列表值作为左值,因为这会修改LIST的元素。 # Trashes @array :( 破坏了@array Print “just another perl hacker” using maximal obfuscation 用最令人困惑的方法写perl俳句 The chr function in the map block below converts a single number into the corresponding ASCII character. The () = /.../g syntax decomposes the string of digits into a list of strings,each three digits long. 下面例子中map程序块儿中的chr函数可以将一个数字转换成对应的ASCII字符。() = /.../g语法将整个数字串分解成一个由字符串组成的列表。每个字符串由三个数字组成。 print map( { chr } Transpose a matrix 转换矩阵 This works with square or rectangular matrices. 可以用来运算方形矩阵或者矩形矩阵 @matrix = ( [1,2,3],[4,5,6],[7,8,9] ); Find prime numbers: a cautionary tale 寻找素数:一个警戒性的事件 Lastly,an example of how NOT to use map. Once you become proficient with map,it is tempting to apply it to every problem involving an array or hash. This can lead to unfortunate code like this: 最后要讲一个不可以使用map的例子。一旦你精通了map的用法,它会诱惑你在任何涉及到数组或哈希表的问题中使用map。但这会导致你写一些并不恰当的代码,如下: foreach $num (1 .. 1000) { This works,but the code is such an evil mess that it made my dog cry. This code violates rule 1 from the classic work The Elements of Programming Style: Write clearly – don’t be too clever. 它能够运行,但是程序代码却是太可怕了,很难搞懂。因为它违反了经典《程序设计式样原理》 的第一条法则:写代码要清晰 - 不要自作聪明。 Look at how easy it is to understand a straightforward implementation of the same algorithm: 看看同样的算法,下面是如何用易懂、直接的语法来实现的: CANDIDATE: foreach $num (1 .. 1000) { As a bonus,the simple implementation is two orders of magnitude faster than the self-generating code! In general,the simpler your code looks,the more the compiler can optimize it. Of course,a complex implementation of a fast algorithm (e.g.,the Fast Fourier Transform) can trump a simple implementation of a slow algorithm. 另外,这种简单的实现方法比刚才那个恐怖的代码要快两个数量级!总的来说,你的代码看起来越简单,编译器就越能优化它。当然,为了实现更快算法的复杂实现(如更快傅立叶转换)要比慢的算法的简单实现要快很多。 Now that we have gazed upon the Dark Side,let us return to the path of righteous,simple code … 现在我们也看到了不好的那一面,那么,朴素的编程风格才是正道。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |