假设我的perl
程序中有以下两个大小相等的数组:
my @arr1 = 1..5;
my @arr2 = 6..10;
我正在尝试使用核心模块reduce
中定义的函数来获取他们的点积,List::Util
但以下内容对我不起作用:
my $dot_prod = reduce { $arr1[$a] * $arr2[$a] + $arr1[$b] * $arr2[$b] }0..$#arr1;
我得到50作为我的输出,而不是预期的130。
假设我的perl
程序中有以下两个大小相等的数组:
my @arr1 = 1..5;
my @arr2 = 6..10;
我正在尝试使用核心模块reduce
中定义的函数来获取他们的点积,List::Util
但以下内容对我不起作用:
my $dot_prod = reduce { $arr1[$a] * $arr2[$a] + $arr1[$b] * $arr2[$b] }0..$#arr1;
我得到50作为我的输出,而不是预期的130。
该文档描述了reduce
如下行为:
第一次调用将 $a 和 $b 设置为列表的前两个元素,后续调用将通过将 $a 设置为上一次调用的结果并将 $b 设置为列表中的下一个元素来完成。
因此,在这种情况下,第一次迭代reduce
将设置$a = 0
and $b = 1
,因此,执行
$arr1[0] * $arr2[0] + $arr1[1] * $arr2[1]
这个临时结果恰好是20。
现在,对于第二次迭代,$a
将其设置为前一次迭代的结果等$a = 20
和$b = 2
。因此,将执行以下操作
$arr1[20] * $arr2[20] + $arr1[2] * $arr2[2]
这不是我们想要的。
一种可能的解决方法:
0
在作为输入提供的列表前面添加一个首字母,reduce
如下所示:
my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;
从第一次迭代开始,这给了我们想要的结果$a = $b = 0
,我们将计算
0 + $arr[0] * $arr[0]
其结果将是6。
然后在第二次迭代中,我们将有$a = 6
$b = 1
,所以我们将计算
6 + $arr1[1] * $arr2[1]
等等
my @arr1 = 1..3;
my @arr2 = 6..8;
use List::Util qw(reduce sum) ;
my $dot_prod0 = reduce { $a + $arr1[$b] * $arr2[$b] } 0,0..$#arr1; #reduce
print "Dot product0 = ".$dot_prod0."\n";
my $dot_prod1 = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1; #sum map
print "Dot product1 = ".$dot_prod1."\n";
my $dot_prod2 = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1; #reduce map
print "Dot product2 = ".$dot_prod2."\n";
诚实地,
my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1;
不是最易读的。有这个:
my $dot_prod = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1;
但这不使用reduce
. 好吧,我们可以简单地实现sum
而reduce
不是使用 List::Util's,甚至可以内联它:
my $dot_prod = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;
不过,这三种解决方案都不是纯粹的功能性解决方案。