Recherche…


Remarques

La List ( liste liée ) brille en accès séquentiel :

  • accéder au premier élément
  • précédant le début de la liste
  • effacer de la liste

D'un autre côté, ce n'est pas idéal pour un accès aléatoire (c.-à-d. Obtenir le nième élément) et la traversée dans l'ordre inverse , et vous pourriez avoir plus de chance (et de performances) avec la structure de données Array .

Créer une liste par plage

0.18.0

Avant 0.18.0, vous pouvez créer des plages comme ceci:

> range = [1..5]
[1,2,3,4,5] : List number
>
> negative = [-5..3]
[-5,-4,-3,-2,-1,0,1,2,3] : List number
0.18.0

Dans 0.18.0 La syntaxe [1..5] a été supprimée .

> range = List.range 1 5
[1,2,3,4,5] : List number
>
> negative = List.range -5 3
[-5,-4,-3,-2,-1,0,1,2,3] : List number

Les plages créées par cette syntaxe sont toujours inclusives et le pas est toujours 1 .

Créer une liste

> listOfNumbers = [1,4,99]
[1,4,99] : List number
>
> listOfStrings = ["Hello","World"]
["Hello","World"] : List String
>
> emptyList = []   -- can be anything, we don't know yet
[] : List a
>

Sous le capot, List ( liste chaînée ) est construit par la fonction :: (appelée "cons"), qui prend deux arguments: un élément, appelé tête, et une liste (éventuellement vide) à laquelle la tête est ajoutée.

> withoutSyntaxSugar = 1 :: []
[1] : List number
>
> longerOne = 1 :: 2 :: 3 :: []
[1,2,3] : List number
>
> nonemptyTail = 1 :: [2]
[1,2] : List number
>

List ne peut prendre que des valeurs d'un type, donc quelque chose comme [1,"abc"] n'est pas possible. Si vous en avez besoin, utilisez des tuples.

> notAllowed = [1,"abc"]
==================================== ERRORS ====================================

-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm

The 1st and 2nd elements are different types of values.

8|              [1,"abc"]
               ^^^^^
The 1st element has this type:

    number

But the 2nd is:

    String

Hint: All elements should be the same type of value so that we can iterate
through the list without running into unexpected values.


> 

Obtenir des éléments

> ourList = [1,2,3,4,5]
[1,2,3,4,5] : List number
>
> firstElement = List.head ourList
Just 1 : Maybe Int
>
> allButFirst = List.tail ourList
Just [2,3,4,5] : Maybe (List Int)

Cet encapsulation dans le type Maybe se produit à cause du scénario suivant:

Que devrait retourner List.head pour une liste vide? (Rappelez-vous, Elm n'a pas d'exceptions ni de null.)

> headOfEmpty = List.head []
Nothing : Maybe Int
>
> tailOfEmpty = List.tail []
Nothing : Maybe (List Int)
>
> tailOfAlmostEmpty = List.tail [1] -- warning ... List is a *linked list* :)
Just [] : Maybe (List Int)

Transformer chaque élément d'une liste

List.map : (a -> b) -> List a -> List b est une fonction d'ordre supérieur qui applique une fonction à un paramètre à chaque élément d'une liste, renvoyant une nouvelle liste avec les valeurs modifiées.

import String

ourList : List String
ourList = 
    ["wubba", "lubba", "dub", "dub"]

lengths : List Int
lengths = 
    List.map String.length ourList
-- [5,5,3,3]

slices : List String
slices =
    List.map (String.slice 1 3) ourList
-- ["ub", "ub", "ub", "ub"]

Si vous avez besoin de connaître l’index des éléments, vous pouvez utiliser List.indexedMap : (Int -> a -> b) -> List a -> List b :

newList : List String
newList =
    List.indexedMap (\index element -> String.concat [toString index, ": ", element]) ourList
-- ["0: wubba","1: lubba","2: dub","3: dub"] 

Filtrer une liste

List.filter : (a -> Bool) -> List a -> List a est une fonction d'ordre supérieur qui prend une fonction à un paramètre de n'importe quelle valeur à un booléen et applique cette fonction à chaque élément d'une liste donnée, ne garder que les éléments pour lesquels la fonction renvoie True . La fonction que prend List.filter comme premier paramètre est souvent appelée prédicat .

import String

catStory : List String
catStory = 
    ["a", "crazy", "cat", "walked", "into", "a", "bar"]

-- Any word with more than 3 characters is so long!
isLongWord : String -> Bool
isLongWord string =
    String.length string > 3

longWordsFromCatStory : List String
longWordsFromCatStory = 
    List.filter isLongWord catStory

Évaluez ceci dans elm-repl :

> longWordsFromCatStory
["crazy", "walked", "into"] : List String
>
> List.filter (String.startsWith "w") longWordsFromCatStory
["walked"] : List String

Correspondance de motif sur une liste

Nous pouvons faire correspondre les listes comme n'importe quel autre type de données, bien qu'elles soient quelque peu uniques, dans la mesure où le constructeur de la construction des listes est la fonction infixe :: . (Voir l'exemple Création d'une liste pour en savoir plus sur le fonctionnement)

matchMyList : List SomeType -> SomeOtherType
matchMyList myList = 
    case myList of
        [] -> 
            emptyCase

        (theHead :: theRest) ->
            doSomethingWith theHead theRest

Nous pouvons faire correspondre autant d'éléments que nous voulons dans la liste:

hasAtLeast2Elems : List a -> Bool
hasAtLeast2Elems myList =
    case myList of
        (e1 :: e2 :: rest) -> 
            True
    
        _ -> 
            False

hasAtLeast3Elems : List a -> Bool
hasAtLeast3Elems myList =
    case myList of
        (e1 :: e2 :: e3 :: rest) -> 
            True
    
        _ -> 
            False

Obtenir le nième élément de la liste

List ne supporte pas "random access", ce qui signifie qu'il faut plus de travail pour obtenir, disons, le cinquième élément de la liste que le premier élément, et par conséquent, il n'y a pas de fonction List.get nth list . Il faut aller depuis le début ( 1 -> 2 -> 3 -> 4 -> 5 ).

Si vous avez besoin d'un accès aléatoire, vous obtiendrez de meilleurs résultats (et performances) avec des structures de données à accès aléatoire, comme Array , où prendre le premier élément nécessite autant de travail que, par exemple, le 1000ème. (complexité O (1)).

Néanmoins, il est possible (mais découragé) d’obtenir le nième élément:

get : Int -> List a -> Maybe a
get nth list =
    list
        |> List.drop (nth - 1)
        |> List.head

fifth : Maybe Int
fifth = get 5 [1..10]
--    = Just 5

nonexistent : Maybe Int
nonexistent = get 5 [1..3]
--          = Nothing

Encore une fois, cela prend beaucoup plus de travail, plus le nth argument est grand.

Réduire une liste à une valeur unique

Dans Elm, les fonctions de réduction sont appelées "folds", et il existe deux méthodes standard pour "plier" les valeurs: de gauche à foldl , et de droite à droite, foldr .

> List.foldl (+) 0 [1,2,3]
6 : number

Les arguments de foldl et foldr sont les suivants:

  • fonction de réduction : newValue -> accumulator -> accumulator
  • valeur de départ de l' accumulateur
  • liste pour réduire

Un autre exemple avec une fonction personnalisée:

type alias Counts =
    { odd : Int
    , even : Int
    }

addCount : Int -> Counts -> Counts
addCount num counts =
    let
        (incOdd, incEven) =
            if num `rem` 2 == 0
                then (0,1)
                else (1,0)
    in
        { counts
            | odd = counts.odd + incOdd
            , even = counts.even + incEven
        }

> List.foldl
      addCount
      { odd = 0, even = 0 }
      [1,2,3,4,5]
{ odd = 3, even = 2 } : Counts

Dans le premier exemple ci-dessus, le programme se présente comme suit:

List.foldl (+) 0 [1,2,3]
3 + (2 + (1 + 0))
3 + (2 + 1)
3 + 3
6
List.foldr (+) 0 [1,2,3]
1 + (2 + (3 + 0))
1 + (2 + 3)
1 + 5
6

Dans le cas d'une fonction commutative comme (+) il n'y a pas vraiment de différence.

Mais voyez ce qui se passe avec (::) :

List.foldl (::) [] [1,2,3]
3 :: (2 :: (1 :: []))
3 :: (2 :: [1])
3 :: [2,1]
[3,2,1]
List.foldr (::) [] [1,2,3]
1 :: (2 :: (3 :: []))
1 :: (2 :: [3])
1 :: [2,3]
[1,2,3]

Créer une liste en répétant une valeur

> List.repeat 3 "abc"
["abc","abc","abc"] : List String

Vous pouvez donner à List.repeat n'importe quelle valeur:

> List.repeat 2 {a = 1, b = (2,True)}
[{a = 1, b = (2,True)}, {a = 1, b = (2,True)}]
  : List {a : Int, b : (Int, Bool)}

Trier une liste

Par défaut, List.sort trie par ordre croissant.

> List.sort [3,1,5]
[1,3,5] : List number

List.sort besoin que les éléments de la liste soient comparable . Cela signifie: String , Char , number ( Int et Float ), List de comparable ou tuple de comparable .

> List.sort [(5,"ddd"),(4,"zzz"),(5,"aaa")]
[(4,"zzz"),(5,"aaa"),(5,"ddd")] : List ( number, String )

> List.sort [[3,4],[2,3],[4,5],[1,2]]
[[1,2],[2,3],[3,4],[4,5]] : List (List number)

Vous ne pouvez pas trier les listes de Bool ou d'objets avec List.sort . Pour cela, voir Trier une liste avec un comparateur personnalisé.

> List.sort [True, False]
-- error, can't compare Bools

Tri d'une liste avec un comparateur personnalisé

List.sortWith vous permet de trier les listes avec des données de n'importe quelle forme - vous leur fournissez une fonction de comparaison.

compareBools : Bool -> Bool -> Order
compareBools a b =
    case (a,b) of
        (False, True) ->
            LT

        (True, False) ->
            GT

        _ ->
            EQ
        
> List.sortWith compareBools [False, True, False, True]
[False, False, True, True] : List Bool

Inverser une liste

Note: ceci n'est pas très efficace en raison de la nature de la List (voir Remarques ci-dessous). Il vaudra mieux construire la liste de la bonne manière depuis le début que de la construire et de l’inverser.

> List.reverse [1,3,5,7,9]
[9,7,5,3,1] : List number

Tri d'une liste par ordre décroissant

Par défaut, List.sort trie par ordre croissant, avec la fonction de compare .

Il existe deux manières de trier par ordre décroissant: une efficace et une inefficace.

  1. Le moyen efficace : List.sortWith et une fonction de comparaison décroissante.
descending a b =
    case compare a b of
      LT -> GT
      EQ -> EQ
      GT -> LT

> List.sortWith descending [1,5,9,7,3]
[9,7,5,3,1] : List number
  1. La manière inefficace (déconseillée!) : List.sort puis List.reverse .
> List.reverse (List.sort [1,5,9,7,3])
[9,7,5,3,1] : List number

Trier une liste par une valeur dérivée

List.sortBy permet d'utiliser une fonction sur les éléments et d'utiliser son résultat pour la comparaison.

> List.sortBy String.length ["longest","short","medium"]
["short","medium","longest"] : List String
-- because the lengths are: [7,5,6]

Il fonctionne aussi très bien avec les accesseurs de disques:

people =
    [ { name = "John", age = 43 }
    , { name = "Alice", age = 30 }
    , { name = "Rupert", age = 12 }
    ]

> List.sortBy .age people
[ { name = "Rupert", age = 12 }
, { name = "Alice", age = 30 }
, { name = "John", age = 43 }
] : List {name: String, age: number}

> List.sortBy .name people
[ { name = "Alice", age = 30 }
, { name = "John", age = 43 }
, { name = "Rupert", age = 12 }
] : List {name: String, age: number}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow