Quel est le moyen le plus rapide d'obtenir le dernier élément d'une liste dans Haskell. Toujours dans la prochaine itération, je veux supprimer le premier et le dernier élément de la liste. Quelle est la manière la plus élégante de procéder? J'essaie de comprendre la liste, mais cela ne semble pas très efficace!
last
et init
feront le travail très bien pour une seule fois. Cependant, ils sont tous les deux O (n) , donc si vous avez besoin de manipuler souvent les deux extrémités d'une liste, comme vous semblez le laisser entendre, vous voudrez peut-être pensez à utiliser Data.Sequence
à la place, qui prend en charge O (1) l'insertion et la suppression d'éléments aux deux extrémités.
Vous pouvez utiliser la fonction last
pour obtenir le dernier élément d'une liste.
Quant à la façon de supprimer les premier et dernier éléments, vous pouvez utiliser (init . tail)
, mais je ne sais pas à quel point c'est efficace.
Je pense que cette image de Learn You A Haskell montre les fonctions de la liste assez bien:
Je publierai l'implémentation de Prelude car elle n'a pas encore été publiée:
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!"
Notez que j'ai changé le nom de la fonction en listLast
afin de pouvoir l'exécuter sans entrer en conflit avec Prelude normal. Vous pouvez, bien sûr, faire import Prelude hiding(last)
.
last' :: [a] -> a
last' ys = foldl1 (\_ -> \x -> x) ys
C'est O (n), tout comme la liste des fonctions de la bibliothèque intégrée.
Cette réponse se concentre sur le traitement des conditions étranges (comme les listes vides) d'une manière maximale flexible et sur la création de fonctions plus importantes à partir de plus petites en utilisant certaines fonctions de bibliothèque. C'est pas la meilleure réponse pour quelqu'un qui apprend d'abord les listes, mais plutôt quelques étapes après cela.
Pour les éléments suivants, vous aurez besoin
import Control.Monad ((>=>))
et vous devrez utiliser GHC 7.10 et importer Data.List (uncons)
ou définir
uncons :: [a] -> Maybe (a, [a])
uncons [] = Nothing
uncons (x:xs) = Just (x,xs)
Vous pouvez écrire une forme sûre de init
comme ceci:
init' :: [x] -> Maybe [x]
init' = foldr go Nothing
where
go x mxs = Just (maybe [] (x:) mxs)
Une version de tail
peut être écrite
tail' :: [a] -> Maybe [a]
tail' = fmap snd . uncons
Alors, vous pouvez obtenir un Maybefied
trim' :: [a] -> Maybe [a]
trim' = init' >=> tail'
Le >=>
Est une sorte de composition monadique à l'envers. init' >=> tail'
Est une fonction qui applique init'
À son argument pour obtenir un Maybe [a]
. S'il obtient Nothing
, il le renvoie. S'il obtient Just xs
, Il applique tail'
À xs
et le renvoie.
À partir de cela, vous pouvez facilement créer un trimmer qui coupe les listes avec 0, 1 ou 2 éléments jusqu'à des listes vides:
trim :: [a] -> [a]
trim = maybe [] id . trim'
Pour supprimer le premier et le dernier:
take (len(l)-2) (drop 1 l)
ou peut-être
init (drop 1 l)
Cela se traduit également par un code presque optimal.