假设我的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 。
答案 0 :(得分:6)
documentation描述了reduce
的行为,如下所示:
第一个调用将是$ a和$ b设置为前两个元素 在列表中,后续调用将通过将$ a设置为结果来完成 上一次调用,$ b到列表中的下一个元素。
因此,在这种情况下,在第一次迭代reduce
将设置$a = 0
和$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]
等
答案 1 :(得分:0)
真的,
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,甚至可以内联它:
my $dot_prod = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;
但这三种解决方案中没有一种纯粹是功能性的。
答案 2 :(得分:0)
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";