this answer on CodeReview中,提问者和回答者似乎都对(++)运算符表示不屑。这是由于它的速度(导致算法在O(n ^ 2)中显式运行,其中n是列表iirc的长度)吗?如果未经其他测试,这是否是预优化,因为Haskell因难以推理时间复杂性而闻名?其他人应该在程序中避免使用(++)运算符吗?

最佳答案

取决于。

考虑表达

foldl (++) [] list

该表达式将列表的列表连接为单个列表,但是具有上述二次复杂度。发生这种情况是因为(++)的实现遍历了整个左侧列表,并将每个元素都添加到了右侧列表中(同时保持正确的顺序)。

使用正确的折痕,我们得到线性复杂度:
foldr (++) [] list

这是由于(++)运算符的实现所致,该实现仅遍历左侧参数并将其前置在右侧。
[1,2] ++ [3,4] ++ [5,6]

等于
-- Example as created by foldr
[1,2] ++ ([3,4] ++ [5,6])
== [1,2] ++ [3,4,5,6]
== [1,2,3,4,5,6] -- all good, no element traversed more than once

仅遍历每个列表元素一次。

现在,将括号切换到前两个列表的开销更大,因为现在多次遍历了某些元素,因此效率很低。
-- Example as created by foldl
([1,2] ++ [3,4]) ++ [5,6]
== [1,2,3,4] ++ [5,6]
== [1,2,3,4,5,6] -- the sublist [1,2] was traversed twice due to the ordering of the appends

总而言之,当心此类情况,您应该会很好。

08-25 23:30