在Haskell中,有两个函数允许对项目列表执行操作,以便将其减少为单个值。 (当然,有两个以上,但这些是我感兴趣的两个。)它们是foldl1
和foldr1
。如果要执行的操作是commutative(例如添加),则使用这些操作无关紧要。结果将是相同的。但是,如果操作不可交换(例如,减法),则两者产生非常不同的结果。例如:
foldr1 (-) [1..9]
foldl1 (-) [1..9]
第一个答案是5,第二个答案是-43。等效于foldr1
的J是插入副词/
,例如,
-/ 1+i.9
相当于foldr1 (-) [1..9]
。我想在J中创建一个类似于插入副词的副词,但是向左折叠而不是向右折叠。我能想到的最好的是:
foldl =: 1 : 'u~/@|.'
因此,可以说:
- foldl 1+i.9
并得到-43作为答案,这是从左侧折叠中得到的结果。
在J中有更好的方法吗?出于某种原因,反转y
论证对我来说似乎并不合适。也许有一种方法可以做到这一点,而不必诉诸于此。
答案 0 :(得分: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
但是你的方式在空间和时间上都比更好。
答案 1 :(得分:1)
($:@}:-{:)^:(1<#) 1+i.9
_43
不知道它是否更高(或更低)效率。