3

假设我的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

4

3 回答 3

6

文档描述了reduce如下行为:

第一次调用将 $a 和 $b 设置为列表的前两个元素,后续调用将通过将 $a 设置为上一次调用的结果并将 $b 设置为列表中的下一个元素来完成。

因此,在这种情况下,第一次迭代reduce将设置$a = 0and $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]

等等

于 2013-01-15T21:54:43.973 回答
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";
于 2020-05-09T01:07:17.270 回答
0

诚实地,

my $dot_prod = reduce { $a + $arr1[$b] * $arr2[$b] } 0, 0..$#arr1; 

不是最易读的。有这个:

my $dot_prod = sum map { $arr1[$_]*$arr2[$_] } 0..$#arr1;

但这不使用reduce. 好吧,我们可以简单地实现sumreduce不是使用 List::Util's,甚至可以内联它:

my $dot_prod = reduce { $a+$b } map { $arr1[$_]*$arr2[$_] } 0..$#arr1;

不过,这三种解决方案都不是纯粹的功能性解决方案。

于 2013-01-16T00:04:14.687 回答