Каков самый быстрый способ получить последний элемент списка в Haskell. Также на следующей итерации я хочу удалить первый и последний элемент списка. Какой самый элегантный способ сделать это? Я пытаюсь понять список, но это выглядит не очень эффективно!
Самый быстрый способ получить последний элемент списка в Haskell
Ответ 1
last
и init
отлично справятся с заданием для одноразового использования. Однако они оба O (n), поэтому, если вам нужно часто манипулировать обоими концами списка, как вы, кажется, подразумеваете, вы можете рассмотреть возможность использования Data.Sequence
, который поддерживает O (1) вставку и удаление элементов с обоих концов.
Ответ 2
Вы можете использовать функцию last
, чтобы получить последний элемент списка.
Как удалить первый и последний элементы, вы можете использовать (init . tail)
, но я не знаю, насколько это эффективно.
Я думаю, что это изображение из Learn You A Haskell показывает, что функции списка довольно хорошо:
Ответ 3
Я опубликую реализацию Prelude, поскольку она еще не была опубликована:
listLast :: [a] -> a
listLast [x] = x --base case is when there just one element remaining
listLast (_:xs) = listLast xs --if there anything in the head, continue until there one element left
listLast [] = error "Can't do last of an empty list!"
Обратите внимание, что я изменил имя функции на listLast
, чтобы ее можно было запустить без конфликта с обычной прелюдией. Вы могли бы, конечно, сделать import Prelude hiding(last)
.
Ответ 4
Чтобы удалить первый и последний:
take (len(l)-2) (drop 1 l)
или, возможно,
init (drop 1 l)
Это также приводит к почти оптимальному коду.
Ответ 5
В этом ответе основное внимание уделяется устранению странных условий (например, пустых списков) максимально гибким способом и созданию больших функций из меньших, использующих некоторые библиотечные функции. Это не лучший ответ для того, чтобы кто-то сначала узнал о списках, а несколько шагов назад.
Для следующего вам понадобится
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
Итак, вы можете получить iffied
trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
>=>
представляет собой своего рода обратную монадическую композицию. init' >=> tail'
- это функция, которая применяет init'
к своему аргументу для получения Maybe [a]
. Если он получает Nothing
, он возвращает это. Если он получает Just xs
, он применяет tail'
к xs
и возвращает это.
Из этого вы можете легко создать триммер, который обрезает списки с 0, 1 или 2 элементами до пустых списков:
trim :: [a] -> [a]
trim = maybe [] id . trim'
Ответ 6
(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])
- другой вариант. Но я думаю, что медленнее из-за двойного разворота.