5

在 Haskell 中,有两个函数允许对项目列表执行操作,以便将其减少为单个值。(当然不止两个,但这是我感兴趣的两个。)它们是foldl1foldr1。如果要执行的操作是可交换的(例如加法),则使用其中的哪一个都没有关系。结果将是相同的。但是,如果运算不是可交换的(例如,减法),那么两者会产生非常不同的结果。例如:

foldr1 (-) [1..9]
foldl1 (-) [1..9]

第一个答案是 5,第二个答案是 -43。J 相当于 offoldr1是插入副词/,例如,

-/ 1+i.9

这相当于foldr1 (-) [1..9]。我想在 J 中创建一个类似于插入副词的副词,但向左折叠而不是向右折叠。我能想到的最好的方法如下:

foldl =: 1 : 'u~/@|.'

因此,可以说:

- foldl 1+i.9

并得到 -43 作为答案,这是左折叠所期望的。

在 J 中有没有更好的方法来做到这一点?出于某种原因,扭转y论点对我来说似乎没有效率。也许有一种方法可以做到这一点而不必诉诸于此。

4

2 回答 2

3

我认为没有比您描述的更好的向左折叠方法了:

(v~) / (|. list)

这是一种非常自然的方式,几乎是“字面”定义的实现。反转列表的成本非常小(imo)。

实现左折叠的另一种明显方法是设置

new_list = (first v second) v rest

例如:

foldl_once =: 1 :'(u / 0 1 { y), (2}. y)'
foldl =: 1 :'(u foldl_once)^:(<:#y) y'

所以:

- foldl >:i.9
_43

但是你的方式在空间和时间上都比这好得多

于 2011-03-09T18:38:10.043 回答
1
   ($:@}:-{:)^:(1<#) 1+i.9
_43

不知道它是否更有效率(或更少)。

于 2011-03-08T03:57:06.670 回答