Elm Language
Listen und Iteration
Suche…
Bemerkungen
Die List ( verknüpfte Liste ) wird im sequenziellen Zugriff angezeigt :
- Zugriff auf das erste Element
- vorangestellt an der Spitze der Liste
- Löschen von der Vorderseite der Liste
Andererseits ist es nicht ideal für den Direktzugriff (dh das n-te Element) und das Durchlaufen in umgekehrter Reihenfolge , und Sie haben mit der Array Datenstruktur möglicherweise mehr Glück (und Leistung).
Liste nach Bereich erstellen
Vor 0.18.0 können Sie Bereiche wie folgt erstellen:
> range = [1..5]
[1,2,3,4,5] : List number
>
> negative = [-5..3]
[-5,-4,-3,-2,-1,0,1,2,3] : List number
In 0.18.0 wurde die [1..5] entfernt .
> 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
Bereiche, die mit dieser Syntax erstellt werden, sind immer inklusive und der Schritt ist immer 1 .
Liste erstellen
> 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
>
Unter der Haube wird List ( verknüpfte Liste ) durch die Funktion :: ("cons" genannt) gebildet, die zwei Argumente akzeptiert: ein Element, das als Kopf bezeichnet wird, und eine (möglicherweise leere) Liste, der der Kopf vorangestellt wird.
> withoutSyntaxSugar = 1 :: []
[1] : List number
>
> longerOne = 1 :: 2 :: 3 :: []
[1,2,3] : List number
>
> nonemptyTail = 1 :: [2]
[1,2] : List number
>
List kann nur Werte eines Typs annehmen, daher ist etwas wie [1,"abc"] nicht möglich. Wenn Sie dies benötigen, verwenden Sie Tupel.
> 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.
>
Elemente bekommen
> 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)
Dieser Umbruch in " Maybe " erfolgt aufgrund des folgenden Szenarios:
Was soll List.head für eine leere Liste zurückgeben? (Denken Sie daran, dass Elm keine Ausnahmen oder Nullen hat.)
> 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)
Jedes Element einer Liste umwandeln
List.map : (a -> b) -> List a -> List b ist eine Funktion höherer Ordnung, die auf jedes Element einer Liste eine Einparameterfunktion anwendet und eine neue Liste mit den geänderten Werten zurückgibt.
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"]
Wenn Sie den Index der Elemente kennen müssen, können Sie 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"]
Eine Liste filtern
List.filter : (a -> Bool) -> List a -> List a ist eine Funktion höherer Ordnung, die eine Ein-Parameter-Funktion von einem beliebigen Wert in einen Booleschen Wert übernimmt und diese Funktion auf jedes Element einer gegebenen Liste anwendet. Es werden nur die Elemente beibehalten, für die die Funktion True zurückgibt. Die Funktion, die List.filter als ersten Parameter verwendet, wird häufig als Prädikat bezeichnet .
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
Bewerten Sie dies in elm-repl :
> longWordsFromCatStory
["crazy", "walked", "into"] : List String
>
> List.filter (String.startsWith "w") longWordsFromCatStory
["walked"] : List String
Musterabgleich auf einer Liste
Wir können wie jeder andere Datentyp auf Listen übereinstimmen, obwohl sie etwas einzigartig sind, dass der Konstruktor für Listen Aufbau ist die Infix Funktion :: . (Siehe Beispiel Erstellen einer Liste für weitere Informationen zur Funktionsweise.)
matchMyList : List SomeType -> SomeOtherType
matchMyList myList =
case myList of
[] ->
emptyCase
(theHead :: theRest) ->
doSomethingWith theHead theRest
Wir können beliebig viele Elemente in der Liste zuordnen:
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
N-tes Element aus der Liste holen
List unterstützt keinen "Direktzugriff", was bedeutet, dass mehr Arbeit erforderlich ist, um z. B. das fünfte Element aus der Liste zu erhalten als das erste Element. Infolgedessen gibt es keine List.get nth list . Man muss den ganzen Weg von Anfang an gehen ( 1 -> 2 -> 3 -> 4 -> 5 ).
Wenn Sie Direktzugriff benötigen, erzielen Sie möglicherweise bessere Ergebnisse (und Leistung) mit Datenstrukturen mit Direktzugriff, wie z. B. Array , bei denen die Übernahme des ersten Elements die gleiche Menge an Arbeit erfordert wie beispielsweise das 1000ste. (Komplexität O (1)).
Trotzdem ist es möglich (aber entmutigt) , das n-te Element zu erhalten:
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
Dies erfordert wiederum deutlich mehr Arbeit, je größer das nth Argument ist.
Eine Liste auf einen einzelnen Wert reduzieren
In Elm werden reduzierende Funktionen "Falten" genannt, und es gibt zwei Standardmethoden, um die Werte nach oben zu "falten": von links nach foldl und von rechts nach foldr .
> List.foldl (+) 0 [1,2,3]
6 : number
Die Argumente für foldl und foldr sind:
- Reduzierfunktion :
newValue -> accumulator -> accumulator - Startwert des Akkus
- Liste zu reduzieren
Noch ein Beispiel mit benutzerdefinierten Funktionen:
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
Im ersten Beispiel oben sieht das Programm folgendermaßen aus:
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
Bei einer kommutativen Funktion wie (+) gibt es keinen wirklichen Unterschied.
Aber schau was passiert mit (::) :
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]
Erstellen einer Liste durch Wiederholen eines Wertes
> List.repeat 3 "abc"
["abc","abc","abc"] : List String
Sie können List.repeat beliebigen Wert geben:
> List.repeat 2 {a = 1, b = (2,True)}
[{a = 1, b = (2,True)}, {a = 1, b = (2,True)}]
: List {a : Int, b : (Int, Bool)}
Liste sortieren
Standardmäßig wird List.sort in aufsteigender Reihenfolge sortiert.
> List.sort [3,1,5]
[1,3,5] : List number
List.sort benötigt comparable List.sort . Das bedeutet: String , Char , number ( Int und Float ), List von comparable oder Tupel von 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)
Sie können Listen von Bool oder Objekten nicht mit List.sort . Siehe dazu Liste mit benutzerdefiniertem Vergleicher sortieren.
> List.sort [True, False]
-- error, can't compare Bools
Sortieren einer Liste mit benutzerdefiniertem Vergleicher
List.sortWith können Sie Listen mit Daten beliebiger Form sortieren - Sie liefern eine Vergleichsfunktion.
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
Liste umkehren
Hinweis: Dies ist aufgrund der Art der List nicht sehr effizient (siehe Anmerkungen unten). Es ist besser, die Liste von Anfang an auf die "richtige" Weise zu erstellen, als sie zu konstruieren und dann umzukehren.
> List.reverse [1,3,5,7,9]
[9,7,5,3,1] : List number
Eine Liste in absteigender Reihenfolge sortieren
Standardmäßig sortiert List.sort in aufsteigender Reihenfolge mit der compare Funktion.
Es gibt zwei Möglichkeiten, in absteigender Reihenfolge zu sortieren: eine effiziente und eine ineffiziente.
- Der effiziente Weg :
List.sortWithund eine absteigende Vergleichsfunktion.
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
- Der ineffiziente Weg (entmutigt!) :
List.sortund dannList.reverse.
> List.reverse (List.sort [1,5,9,7,3])
[9,7,5,3,1] : List number
Sortieren einer Liste nach einem abgeleiteten Wert
List.sortBy ermöglicht die Verwendung einer Funktion für die Elemente und deren Ergebnis für den Vergleich.
> List.sortBy String.length ["longest","short","medium"]
["short","medium","longest"] : List String
-- because the lengths are: [7,5,6]
Es funktioniert auch gut mit Record Accessoren:
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}