在Haskell中获取列表的最后一个元素的最快方法是什么。同样在下一次迭代中,我想删除列表的第一个和最后一个元素。最优雅的方式是什么?我正在尝试列表理解,但这看起来效率不高!
答案 0 :(得分:77)
您可以使用the last
function获取列表的最后一个元素。
至于如何删除第一个和最后一个元素,可以使用(init . tail)
,但我不知道它的效率如何。
我认为来自Learn You A Haskell的图片显示列表功能相当不错:
答案 1 :(得分:36)
last
和init
可以完成一次性工作。但是它们都是 O(n),所以如果你需要经常操作列表的两端,就像你似乎暗示的那样,你可能想要考虑使用Data.Sequence
代替它,它支持 O(1)插入和移除两端的物品。
答案 2 :(得分:5)
我将发布Prelude实施,因为尚未发布:
listLast :: [a] -> a
listLast [x] = x --base case is when there's just one element remaining
listLast (_:xs) = listLast xs --if there's anything in the head, continue until there's one element left
listLast [] = error "Can't do last of an empty list!"
请注意,我将函数名称更改为listLast
,以便可以在不与正常Prelude冲突的情况下运行它。当然,你可以做import Prelude hiding(last)
。
答案 3 :(得分:0)
要删除第一个和最后一个:
take (len(l)-2) (drop 1 l)
或者
init (drop 1 l)
这也会产生几乎最优的代码。
答案 4 :(得分:0)
这个答案的重点是以最灵活的方式处理奇怪的条件(如空列表),以及使用一些库函数从较小的函数构建更大的函数。对于第一次了解列表的人来说,它不是不是的最佳答案,而是过去的几步。
对于以下内容,您需要
import Control.Monad ((>=>))
您需要使用GHC 7.10并导入Data.List (uncons)
或定义
uncons :: [a] -> Maybe (a, [a])
uncons [] = Nothing
uncons (x:xs) = Just (x,xs)
您可以像这样写一个init
的安全表单:
init' :: [x] -> Maybe [x]
init' = foldr go Nothing
where
go x mxs = Just (maybe [] (x:) mxs)
可以编写tail
版本
tail' :: [a] -> Maybe [a]
tail' = fmap snd . uncons
那么你可以得到一个可能的
trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
>=>
是一种向后的monadic组合。 init' >=> tail'
是一个将init'
应用于其参数以获取Maybe [a]
的函数。如果它得到Nothing
,则返回该值。如果它获得Just xs
,则会将tail'
应用于xs
并返回该值。
通过这种方式,您可以轻松制作修剪器,将包含0,1或2个元素的列表修剪为空列表:
trim :: [a] -> [a]
trim = maybe [] id . trim'
答案 5 :(得分:0)
last' :: [a] -> a
last' ys = foldl1 (\_ -> \x -> x) ys
它是O(n),就像内置的库函数列表一样。
答案 6 :(得分:-2)
(head.reverse) [1..100]
是获取最后一个元素的替代last
。
drop 1 (take (length [1..100] - 1) [1..100])
删除第一个和最后一个列表元素。 drop
和take
的来源看起来可能比(init . tail)
更快。
(reverse.drop 1) ((reverse.drop 1) [1..100])
是另一种变体。但我认为因双重逆转而放慢速度。