Sök…


Anmärkningar

List ( länkad lista ) lyser i sekvensiell åtkomst :

  • åtkomst till det första elementet
  • förbereda till framsidan av listan
  • ta bort från listans framsida

Å andra sidan är det inte idealiskt för slumpmässig åtkomst (dvs. att få det n: a elementet) och genomföra i omvänd ordning , och du kan få bättre tur (och prestanda) med Array datastrukturen.

Skapa en lista efter intervall

0.18.0

Innan 0.18.0 kan du skapa områden som detta:

> 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

I 0.18.0 har syntaxen [1..5] tagits bort .

> 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

Områden som skapas av denna syntax är alltid inkluderande och steget är alltid 1 .

Skapa en lista

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

Under huven är List ( länkad lista ) konstruerad av :: -funktionen (kallas "nackdelar"), som tar två argument: ett element, känt som huvudet, och en (eventuellt tom) lista som huvudet är förberedt för.

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

List kan bara ta värden av en typ, så något som [1,"abc"] är inte möjligt. Om du behöver detta, använd 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.


> 

Få element

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

Denna inpackning i Maybe typen händer på grund av följande scenario:

Vad ska List.head returnera för en tom lista? (Kom ihåg att Elm inte har undantag eller noll.)

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

Omvandla varje element i en lista

List.map : (a -> b) -> List a -> List b är en högre ordningsfunktion som tillämpar en enparameterfunktion på varje element i en lista och returnerar en ny lista med de ändrade värdena.

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

Om du behöver känna till indexet för elementen kan du använda 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"] 

Filtrera en lista

List.filter : (a -> Bool) -> List a -> List a är en högre ordningsfunktion som tar en enparameterfunktion från vilket värde som helst till en booleska, och tillämpar den funktionen för varje element i en given lista, behåller bara de element för vilka funktionen returnerar True på. Funktionen som List.filter tar som sin första parameter benämns ofta ett predikat .

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

Utvärdera detta i elm-repl :

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

Mönstermatchning på en lista

Vi kan matcha på listor som alla andra datatyper, även om de är något unika, eftersom konstruktören för att bygga upp listor är infixfunktionen :: . (Se exemplet Skapa en lista för mer information om hur det fungerar.)

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

        (theHead :: theRest) ->
            doSomethingWith theHead theRest

Vi kan matcha så många element i listan som vi vill:

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

Få det nionde elementet från listan

List stöder inte "slumpmässig åtkomst", vilket innebär att det kräver mer arbete för att säga, det femte elementet från listan än det första elementet, och som ett resultat finns det ingen List.get nth list . Man måste gå hela vägen från början ( 1 -> 2 -> 3 -> 4 -> 5 ).

Om du behöver slumpmässig åtkomst kan du få bättre resultat (och prestanda) med datastrukturer med slumpmässig åtkomst, som Array , där du tar det första elementet med samma mängd arbete som att ta, säga, 1000: e. (komplexitet O (1)).

Ändå är det möjligt (men avskräckt) att få det n: a elementet:

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

Återigen tar detta betydligt mer arbete desto större är det nth argumentet.

Minska en lista till ett enda värde

I Elm kallas reduceringsfunktioner "veck", och det finns två standardmetoder för att "vika" värden upp: från vänster, foldl och från höger, foldr .

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

Argumenten för att foldl och foldr är:

  • reducerande funktion : newValue -> accumulator -> accumulator
  • ackumulatorens startvärde
  • lista för att minska

Ett ytterligare exempel med anpassad funktion:

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

I det första exemplet ovan går programmet så här:

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

När det gäller en kommutativ funktion som (+) finns det egentligen ingen skillnad.

Men se vad som händer med (::) :

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]

Skapa en lista genom att upprepa ett värde

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

Du kan ge List.repeat valfritt värde:

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

Sortera en lista

Som standard sorterar List.sort i stigande ordning.

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

List.sort behöver att List.sort är comparable . Det betyder: String , Char , number ( Int och Float ), List över comparable eller tupel av 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)

Du kan inte sortera listor över Bool eller objekt med List.sort . Se Sortera en lista med anpassad komparator.

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

Sortera en lista med anpassad komparator

List.sortWith låter dig sortera listor med data av vilken form som helst - du ger den en jämförelsefunktion.

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

Omvända en lista

Obs: detta är inte särskilt effektivt på grund av List karaktär (se anmärkningar nedan). Det kommer att vara bättre att konstruera listan på "rätt" sätt från början än att konstruera den och sedan vända den.

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

Sortera en lista i fallande ordning

Som standard sorterar List.sort i stigande ordning med compare funktionen.

Det finns två sätt att sortera i fallande ordning: ett effektivt och ett ineffektivt.

  1. Det effektiva sättet : List.sortWith och en fallande jämförelsefunktion.
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. Det ineffektiva sättet (avskräckt!) : List.sort och sedan List.reverse .
> List.reverse (List.sort [1,5,9,7,3])
[9,7,5,3,1] : List number

Sortera en lista efter ett härledt värde

List.sortBy tillåter att använda en funktion på elementen och använda dess resultat för jämförelsen.

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

Det fungerar också fint med skivtillbehör:

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow