在Haskell中获取列表的最后一个元素的最快方法

时间:2011-09-11 07:38:26

标签: haskell list-comprehension

在Haskell中获取列表的最后一个元素的最快方法是什么。同样在下一次迭代中,我想删除列表的第一个和最后一个元素。最优雅的方式是什么?我正在尝试列表理解,但这看起来效率不高!

7 个答案:

答案 0 :(得分:77)

您可以使用the last function获取列表的最后一个元素。

至于如何删除第一个和最后一个元素,可以使用(init . tail),但我不知道它的效率如何。

我认为来自Learn You A Haskell的图片显示列表功能相当不错:

illustration of list functions

答案 1 :(得分:36)

lastinit可以完成一次性工作。但是它们都是 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])

删除第一个和最后一个列表元素。 droptake的来源看起来可能比(init . tail)更快。

(reverse.drop 1) ((reverse.drop 1) [1..100])

是另一种变体。但我认为因双重逆转而放慢速度。