自从我前一段时间学习Haskell以来,我不断看到人reverse
列表,只是稍后反过来。以下用于使用分隔符拆分字符串的函数是一个示例:
splitOn ::Eq a => a -> [a] -> [[a]]
splitOn sep str = s_word str []
where s_word [] w = [reverse w]
s_word (c:cs) w = if (c == sep) then reverse w : s_word cs []
else s_word cs (c:w)
我认为原因是“缺乏”正确/反向利弊运算符,如:
rcons xs x = xs ++ [x]
当然,rcons
的效率远低于cons
运算符(:
)。
但是上面的代码似乎通过使用reverse
来介绍它自己的低效率。我想知道它是否比以下变体更有效或效率更低:
splitOn' ::Eq a => a -> [a] -> [[a]]
splitOn' sep str = s_word str []
where s_word [] w = [w]
s_word (c:cs) w = if (c == sep) then w : s_word cs []
else s_word cs (rcons w c)
这两个功能似乎都达到了同样的效果。我认为第二个版本似乎更直观(虽然可能不那么聪明)。使用这样的rcons
是否有任何陷阱? (无限名单,懒惰等)。
感谢。
P.S。输出:
*Main> splitOn' ',' "a,b,"
["a","b",""]
答案 0 :(得分:6)
如果使用“double reverse”来添加单个元素,rcons
可能会更有效率,因为它只会遍历输入列表一次,而每个reverse
一次只会遍历输入列表遍历遍历。
但是,在您提供的splitOn'
示例中,reverse
仅在每个输出字中使用一次,因为该值以反向形式开始累积。更重要的是,(:)
将在调用reverse
之前多次使用。
在使用rcons
的替代方案中,每个新元素都会对列表进行线性遍历,而对于reverse
,一旦结果准备好,就会只进行一次线性遍历。