Zoeken…


Opmerkingen

De List ( gekoppelde lijst ) schittert in opeenvolgende toegang :

  • toegang tot het eerste element
  • vooraan in de lijst
  • verwijderen vanaf de voorkant van de lijst

Aan de andere kant is het niet ideaal voor willekeurige toegang (bijv. Het verkrijgen van het nde element) en verplaatsing in omgekeerde volgorde , en u hebt misschien meer geluk (en prestaties) met de gegevensstructuur van de Array .

Een lijst op bereik maken

0.18.0

Voorafgaand aan 0.18.0 kunt u bereiken als deze maken:

> 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

In 0.18.0 De syntaxis [1..5] is verwijderd .

> 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

Bereiken die door deze syntaxis zijn gemaakt, zijn altijd inclusief en de stap is altijd 1 .

Een lijst maken

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

Onder de motorkap wordt List ( gekoppelde lijst ) samengesteld door de :: functie ("cons" genoemd), waarvoor twee argumenten nodig zijn: een element, bekend als de kop, en een (mogelijk lege) lijst waaraan de kop is voorafgegaan.

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

List kan slechts waarden van één type aannemen, dus zoiets als [1,"abc"] is niet mogelijk. Gebruik tupels als je dit nodig hebt.

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


> 

Elementen ophalen

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

Deze verpakking in het type Maybe gebeurt vanwege het volgende scenario:

Wat moet List.head opleveren voor een lege lijst? (Vergeet niet dat Elm geen uitzonderingen of nulwaarden heeft.)

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

Elk element van een lijst transformeren

List.map : (a -> b) -> List a -> List b is een functie van hogere orde die een functie met één parameter toepast op elk element van een lijst en een nieuwe lijst met de gewijzigde waarden retourneert.

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"]

Als u de index van de elementen moet weten, kunt u 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"] 

Een lijst filteren

List.filter : (a -> Bool) -> List a -> List a is een functie van een hogere orde die een functie met één parameter van een willekeurige waarde naar een Boolean neemt en die functie op elk element van een gegeven lijst toepast, alleen die elementen behouden waarvoor de functie True aan retourneert. De functie die List.filter als eerste parameter aanneemt, wordt vaak een predicaat genoemd .

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

Evalueer dit in elm-repl :

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

Patroonovereenkomst op een lijst

We kunnen op lijsten matchen als elk ander gegevenstype, hoewel ze enigszins uniek zijn, omdat de constructor voor het samenstellen van lijsten de infixfunctie is :: . (Zie het voorbeeld Een lijst maken voor meer informatie over hoe dat werkt.)

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

        (theHead :: theRest) ->
            doSomethingWith theHead theRest

We kunnen zoveel elementen in de lijst matchen als we willen:

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

Nde element uit de lijst krijgen

List ondersteunt geen "willekeurige toegang", wat betekent dat er meer werk nodig is om bijvoorbeeld het vijfde element uit de lijst te krijgen dan het eerste element, en bijgevolg is er geen List.get nth list . Men moet helemaal vanaf het begin gaan ( 1 -> 2 -> 3 -> 4 -> 5 ).

Als u willekeurige toegang nodig hebt, krijgt u mogelijk betere resultaten (en prestaties) met datastructuren voor willekeurige toegang, zoals Array , waarbij het nemen van het eerste element evenveel werk kost als het nemen van bijvoorbeeld de 1000e. (complexiteit O (1)).

Desondanks is het mogelijk (maar ontmoedigd) om het nde element te krijgen:

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

Nogmaals, dit kost aanzienlijk meer werk naarmate het nth argument groter is.

Een lijst terugbrengen tot één waarde

In Elm worden verkleiningsfuncties "vouwen" genoemd, en er zijn twee standaardmethoden om waarden omhoog te "vouwen": van links, foldl en van rechts, foldr .

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

De argumenten voor foldl en foldr zijn:

  • reducerende functie : newValue -> accumulator -> accumulator
  • startwaarde accumulator
  • lijst om te verkleinen

Nog een voorbeeld met aangepaste functie:

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

In het eerste voorbeeld hierboven ziet het programma er als volgt uit:

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

In het geval van een commutatieve functie zoals (+) er niet echt een verschil.

Maar kijk wat er gebeurt met (::) :

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]

Een lijst maken door een waarde te herhalen

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

U kunt List.repeat elke waarde geven:

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

Een lijst sorteren

Standaard sorteert List.sort in oplopende volgorde.

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

List.sort heeft de List.sort nodig om comparable . Dat betekent: String , Char , number ( Int en Float ), List met comparable of tuple met 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)

U kunt lijsten met Bool of objecten niet sorteren met List.sort . Zie daarvoor Een lijst sorteren met aangepaste comparator.

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

Een lijst sorteren met aangepaste vergelijker

List.sortWith kunt u lijsten sorteren met gegevens van elke vorm - u voorziet deze van een vergelijkingsfunctie.

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

Een lijst omkeren

Opmerking: dit is niet erg efficiënt vanwege de aard van List (zie Opmerkingen hieronder). Het is beter om de lijst vanaf het begin op de "juiste" manier samen te stellen dan deze op te bouwen en vervolgens om te keren.

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

Een lijst in aflopende volgorde sorteren

Standaard sorteert List.sort in oplopende volgorde, met de compare .

Er zijn twee manieren om in aflopende volgorde te sorteren: een efficiënte en een inefficiënte.

  1. De efficiënte manier : List.sortWith en een dalende vergelijkingsfunctie.
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. De inefficiënte manier (ontmoedigd!) : List.sort en vervolgens List.reverse .
> List.reverse (List.sort [1,5,9,7,3])
[9,7,5,3,1] : List number

Een lijst sorteren op een afgeleide waarde

List.sortBy maakt het mogelijk om een functie op de elementen te gebruiken en het resultaat ervan te gebruiken voor de vergelijking.

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

Het werkt ook goed met record accessors:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow