Buscar..


Observaciones

La List ( lista enlazada ) brilla en el acceso secuencial :

  • accediendo al primer elemento
  • antepuesto al frente de la lista
  • borrar de la parte frontal de la lista

Por otro lado, no es ideal para el acceso aleatorio (es decir, obtener el elemento nth) y el desplazamiento en orden inverso , y es posible que tenga más suerte (y rendimiento) con la estructura de datos de Array .

Creando una lista por rango

0.18.0

Antes de 0.18.0 puedes crear rangos como este:

> 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

En 0.18.0 La sintaxis [1..5] ha sido eliminada .

> 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

Los rangos creados por esta sintaxis son siempre inclusivos y el paso es siempre 1 .

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

Bajo el capó, la List ( lista enlazada ) se construye mediante la función :: (llamada "contras"), que toma dos argumentos: un elemento, conocido como la cabecera, y una lista (posiblemente vacía) a la cual se añade la cabecera.

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

List solo puede tomar valores de un tipo, por lo que algo como [1,"abc"] no es posible. Si necesitas esto, usa tuplas.

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


> 

Obteniendo elementos

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

Este ajuste en el tipo Maybe ocurre debido al siguiente escenario:

¿Qué debería devolver List.head por una lista vacía? (Recuerda, Elm no tiene excepciones o nulos).

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

Transformando cada elemento de una lista.

List.map : (a -> b) -> List a -> List b es una función de orden superior que aplica una función de un parámetro a cada elemento de una lista, devolviendo una nueva lista con los valores modificados.

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 necesita conocer el índice de los elementos, puede usar 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"] 

Filtrando una lista

List.filter : (a -> Bool) -> List a -> List a es una función de orden superior que lleva una función de un parámetro de cualquier valor a un booleano, y aplica esa función a cada elemento de una lista dada, manteniendo solo aquellos elementos para los que la función devuelve True . La función que List.filter toma como su primer parámetro a menudo se denomina predicado .

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

Evalúa esto en elm-repl :

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

Coincidencia de patrones en una lista

Podemos coincidir en listas como cualquier otro tipo de datos, aunque son un tanto únicos, ya que el constructor para construir listas es la función de infijo :: . (Consulte el ejemplo Creación de una lista para obtener más información sobre cómo funciona).

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

        (theHead :: theRest) ->
            doSomethingWith theHead theRest

Podemos hacer coincidir tantos elementos en la lista como queramos:

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

Obteniendo el elemento nth de la lista

List no admite el "acceso aleatorio", lo que significa que se necesita más trabajo para obtener, digamos, el quinto elemento de la lista que el primer elemento, y como resultado no hay List.get nth list función de List.get nth list . Uno tiene que ir desde el principio ( 1 -> 2 -> 3 -> 4 -> 5 ).

Si necesita acceso aleatorio, puede obtener mejores resultados (y rendimiento) con estructuras de datos de acceso aleatorio, como Array , donde tomar el primer elemento requiere la misma cantidad de trabajo que tomar, por ejemplo, el 1000. (complejidad O (1)).

Sin embargo, es posible (pero desanimado) obtener el elemento nth:

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

De nuevo, esto requiere mucho más trabajo cuanto más grande sea el nth argumento.

Reduciendo una lista a un solo valor

En Elm, las funciones de reducción se denominan "pliegues", y existen dos métodos estándar para "plegar" los valores: desde la izquierda, foldl , y desde la derecha, foldr .

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

Los argumentos para foldl y foldr son:

  • función reductora : newValue -> accumulator -> accumulator
  • valor de arranque del acumulador
  • lista para reducir

Un ejemplo más con función personalizada:

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

En el primer ejemplo anterior, el programa es el siguiente:

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

En el caso de una función conmutativa como (+) no hay realmente una diferencia.

Pero mira que pasa con (::) :

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]

Creando una lista repitiendo un valor

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

Puedes darle a List.repeat cualquier valor:

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

Ordenar una lista

Por defecto, List.sort ordena en orden ascendente.

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

List.sort necesita que los elementos de la lista sean comparable . Eso significa: String , Char , number ( Int y Float ), List de comparable o tupla 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)

No puede ordenar listas de Bool u objetos con List.sort . Para eso vea Ordenar una lista con un comparador personalizado.

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

Ordenar una lista con comparador personalizado

List.sortWith permite ordenar listas con datos de cualquier forma; usted le proporciona una función de comparación.

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

Invertir una lista

Nota: esto no es muy eficiente debido a la naturaleza de la List (ver Comentarios a continuación). Será mejor construir la lista de la manera "correcta" desde el principio que construirla y luego revertirla.

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

Ordenar una lista en orden descendente

Por defecto, List.sort ordena en orden ascendente, con la función de compare .

Hay dos formas de clasificar en orden descendente: una eficiente y otra ineficiente.

  1. La forma eficiente : List.sortWith y una función de comparación descendente.
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. El modo ineficiente (¡desalentado!) : List.sort y luego List.reverse .
> List.reverse (List.sort [1,5,9,7,3])
[9,7,5,3,1] : List number

Ordenar una lista por un valor derivado

List.sortBy permite usar una función en los elementos y usar su resultado para la comparación.

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

También funciona muy bien con los registros de acceso:

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow