这是perl的map用法示例的第三篇文章了,也是最后一篇介绍map函数用法的,耐心看下去哦.
8. 转置矩阵
@matrix = ( [1, 2, 3], [4, 5, 6], [7, 8, 9] ); foreach $xyz (@matrix) { print "$xyz->;[0] $xyz->;[1] $xyz->;[2]\n"; } @transposed = map { $x = $_; [ map { $matrix[$_][$x] } 0 .. $#matrix ]; } 0 .. $#{$matrix[0]}; print "\n"; foreach $xyz (@transposed) { print "$xyz->;[0] $xyz->;[1] $xyz->;[2]\n";
打印结果是:
1 2 3 4 5 6 7 8 9
1 4 7 2 5 8 3 6 9
这里稍微有点复杂哦,让我们分2步看看。
@matrix = ( [1, 2, 3], [4, 5, 6], [7, 8, 9] ); foreach $xyz (@matrix) { print "$xyz->;[0] $xyz->;[1] $xyz->;[2]\n"; }
这里不难明白,( [1, 2, 3], [4, 5, 6], [7, 8, 9] ) 是个数组,它的每个元素又是个匿名数组,这样在$xyz遍历数组时,$xyz->;[0],$xyz->;[1],$xyz->;[2]就可以访问到匿名数组里的元素了。所以会打印出:
1 2 3 4 5 6 7 8 9
@transposed = map { $x = $_; [ map { $matrix[$_][$x] } 0 .. $#matrix ]; } 0 .. $#{$matrix[0]};
这里复杂点,0 .. $#{$matrix[0]}是个列表,$#{$matrix[0]}表示$matrix[0]这个匿名数组的最大下标值,0 .. $#{$matrix[0]}表示矩阵的横向。$x = $_;这里将$_的值赋给$x,为什么呢?因为它后面又有个map嘛,$_的值会改变的,所以要先存储起来。外围的map返回的值是[]里的map计算出来的一个列表,以[]匿名数组形式返回。[]里面的map是这样的,它的输入LIST是0 .. $#matrix, 表示矩阵的纵向了。$matrix[$_][$x]这里先纵再横,就把矩阵值置换了一下。所以返回的结果列表@transposed就包含置换后的矩阵了哦。
是否有点糊涂?那举例看看。这样看可能好点:
[1, 2, 3], [4, 5, 6], [7, 8, 9]
外围的map遍历时,先是横向下标遍历,停留在横向0位。然后第二个map,就是纵向下标遍历了,它要遍历所有纵向下标,这样在横向0位,就先返回[1,4,7]的列表了,然后在横向1位,又返回[2,5,8]的列表,最后在横向2位,返回[3,6,9]的列表。
9. 查找质数:警示用法
foreach $num (1 .. 1000) { @expr = map { '$_ % ' . $_ . ' &&' } 2 .. int sqrt $num; if (eval "grep { @expr 1 } $num") { print "$num " } }
打印结果是: 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 ...
该代码能工作,但它如此麻烦,违背了程序最基本的明晰法则。用如下直观简洁的代码代替它就可以了呀:
CANDIDATE: foreach $num (1 .. 1000) { foreach $factor (2 .. int sqrt $num) { unless ($num % $factor) { next CANDIDATE } } print "$num "; } |