web-dev-qa-db-fra.com

Le moyen le plus rapide d'obtenir le dernier élément d'une liste dans Haskell

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!

30
Dilawar

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.

38
hammar

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:

illustration of list functions

79
icktoofay

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).

6
user1429980
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.

0
Abhijit Gupta

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'
0
dfeuer

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.

0
nulvinge