这是我当前代码的示例:
DataSet = [1,2,3,4,5,6,7,8,9].
Sequence = [3,4,5,6].
ReducedDataSet = lists:foldl( fun(SeqNumber, Output) ->
Row = lists:nth(SeqNumber, DataSet),
[Row|Output]
end,
[],
Sequence
).
ReducedDataSet最终为[6,5,4,3],如果我将其更改为list:foldr,ReducedDataSet将为[3,4,5,6]。
我没想到这是因为从左到右吸收,第3个值是3并且应该进入6,但是当从右到左吸收时,第3个值将是7,并且继续到4。
这是否意味着我的列表中存在隐藏的行号,而foldl和foldr仅在最终列表的排序顺序上有所不同?
答案 0 :(得分:4)
我认为这是一个更普遍的fold
问题。
通常,fold会执行以下操作:(new_element, acc) -> new_acc
如果操作new_element ° acc
是可交换的(例如sum
),则foldl和foldr是相同的。
如果操作是“追加”,则将元素添加到左侧或右侧之间存在差异。
[3] ° 4 -> [3, 4]
VS 4 ° [3] -> [4, 3]
我永远不会记得哪个是foldl
和foldr
,但我认为左/右指的是累加器的位置([3] ° 4
是foldl
这个定义)
答案 1 :(得分:3)
<强> TL; DR 强>
不,Erlang列表中没有隐藏索引或“行号”。
<强>讨论强>
在“列表是一堆事物”的功能列表的上下文中,更多地探索列表操作的本质可能会有所帮助。
我写了一篇关于折叠的解释,可能对你有用:Explanation of lists:fold function
请记住,功能列表只有指向单向的指针。也就是说,它们是单链表。没有“rownum”或“index”的概念,因为它将在C样式数组中。每次调用lists:nth/2
实际上遍历列表 n 元素,然后返回该元素。
如果我们想要一个在错误输入上崩溃的版本(并且查找它,结果是it is written almost exactly like this),我们可以这样写lists:nth/2
:
nth(1, [Element | _]) ->
Element;
nth(N, [_ | Rest]) when N > 1 ->
lists:nth(N - 1, Rest).
(作为旁注,请考虑not inlining funs that require you to write multi-line definitions as function arguments ...)