elm-community / array-extra / Array.Extra

Convenience functions for working with Array

scan

all : (element -> Basics.Bool) -> Array element -> Basics.Bool

Whether all elements satisfy a given test.

import Array exposing (fromList, empty)

fromList [ 2, 4 ] |> all (\x -> x < 5)
--> True

fromList [ 4, 16 ] |> all (\x -> x < 5)
--> False

empty |> all (\x -> x < 5)
--> True

any : (element -> Basics.Bool) -> Array element -> Basics.Bool

Whether at least some elements satisfy a given test.

import Array exposing (fromList, empty)

fromList [ 6, 3 ] |> any (\x -> x < 5)
--> True

fromList [ 12, 33 ] |> any (\x -> x < 5)
--> False

empty |> any (\x -> x < 5)
--> False

member : element -> Array element -> Basics.Bool

Whether a given value is contained.

import Array exposing (fromList)

fromList [ "Leonardo", "Michelangelo", "Donatello", "Raphael" ]
    |> member "Donatello"
--> True

fromList [ "Leonardo", "Michelangelo" ]
    |> member "Raphael"
--> False

alter

reverse : Array element -> Array element

Flip the element order.

import Array exposing (fromList)

fromList [ 1, 2, 3, 4 ] |> reverse
--> fromList [ 4, 3, 2, 1 ]

intersperse : element -> Array element -> Array element

Place a value between all elements.

import Array exposing (fromList)

fromList [ "turtles", "turtles", "turtles" ]
    |> intersperse "on"
--> fromList
-->     [ "turtles", "on", "turtles", "on", "turtles" ]

To interlace an Array, interweave.

update : Basics.Int -> (element -> element) -> Array element -> Array element

Update the element at a given index based on its current value. If the index is out of bounds, nothing is changed.

import Array exposing (fromList)

fromList [ 1, 2, 3 ] |> update 1 (\n -> n + 10)
--> fromList [ 1, 12, 3 ]

fromList [ 1, 2, 3 ] |> update 4 (\n -> n + 10)
--> fromList [ 1, 2, 3 ]

fromList [ 1, 2, 3 ] |> update -1 (\n -> n + 10)
--> fromList [ 1, 2, 3 ]

pop : Array element -> Array element

Remove the last element.

import Array exposing (fromList, empty)

fromList [ 1, 2, 3 ] |> pop
--> fromList [ 1, 2 ]

empty |> pop
--> empty

removeAt : Basics.Int -> Array element -> Array element

Remove the element at a given index. If the index is out of bounds, nothing is changed.

import Array exposing (fromList)

fromList [ 1, 2, 3, 4 ] |> removeAt 2
--> fromList [ 1, 2, 4 ]

fromList [ 1, 2, 3, 4 ] |> removeAt -1
--> fromList [ 1, 2, 3, 4 ]

fromList [ 1, 2, 3, 4 ] |> removeAt 100
--> fromList [ 1, 2, 3, 4 ]

insertAt : Basics.Int -> element -> Array element -> Array element

Insert an element at a given index. If the index is out of bounds, nothing is changed.

import Array exposing (fromList)

fromList [ 'a', 'c' ] |> insertAt 1 'b'
--> fromList [ 'a', 'b', 'c' ]

fromList [ 'a', 'c' ] |> insertAt -1 'b'
--> fromList [ 'a', 'c' ]

fromList [ 'a', 'c' ] |>  insertAt 100 'b'
--> fromList [ 'a', 'c' ]

filter

removeWhen : (element -> Basics.Bool) -> Array element -> Array element

Only keep elements which fail to satisfy a given predicate. This is equivalent to Array.filter (not << predicate).

import Array exposing (fromList)

fromList [ -1, 92, 0, 14, -3 ]
    |> removeWhen (\x -> x < 0)
--> fromList [ 92, 0, 14 ]

filterMap : (element -> Maybe narrowElement) -> Array element -> Array narrowElement

Try transforming all elements but only keep the successes.

import Array exposing (fromList)

fromList [ "3", "4.0", "5", "hats" ]
    |> filterMap String.toInt
--> fromList [ 3, 5 ]

part

sliceFrom : Basics.Int -> Array element -> Array element

Drop a given number of elements from the start. In other words, slice the Array from an index until the very end. Given a negative argument, count the end of the slice from the end.

import Array exposing (fromList)

fromList (List.range 0 6) |> sliceFrom 3
--> fromList [ 3, 4, 5, 6 ]

fromList (List.range 0 6) |> sliceFrom -3
--> fromList [ 4, 5, 6 ]

sliceUntil : Basics.Int -> Array element -> Array element

Take a number of elements from the start. In other words, slice the Array from the very beginning until not including the index. Given a negative argument, count the beginning of the slice from the end.

import Array exposing (fromList)

fromList (List.range 0 6) |> sliceUntil 3
--> fromList [ 0, 1, 2 ]

fromList (List.range 0 6) |> sliceUntil -3
--> fromList [ 0, 1, 2, 3 ]

splitAt : Basics.Int -> Array element -> ( Array element, Array element )

Split into two Arrays, the first ending before and the second starting with a given index.

import Array exposing (fromList, empty)

fromList [ 1, 2, 3, 4 ] |> splitAt 2
--> ( fromList [ 1, 2 ], fromList [ 3, 4 ] )

fromList [ 1, 2, 3, 4 ] |> splitAt 100
--> ( fromList [ 1, 2, 3, 4 ], empty )

fromList [ 1, 2, 3, 4 ] |> splitAt -1
--> ( empty, fromList [ 1, 2, 3, 4 ] )

combine

interweave : Array element -> Array element -> Array element

Place all elements of a given Array between all current elements. Extra elements of either Array are glued to the end without anything in between.

import Array exposing (fromList, repeat)

fromList [ "turtles", "turtles", "turtles" ]
    |> interweave (repeat 2 "on")
--> fromList [ "turtles", "on", "turtles", "on", "turtles" ]

fromList [ "turtles", "turtles", "turtles" ]
    |> interweave (repeat 5 "on")
--> fromList [ "turtles", "on", "turtles", "on", "turtles", "on", "on", "on" ]

fromList [ "turtles", "turtles", "turtles" ]
    |> interweave (repeat 1 "on")
--> fromList [ "turtles", "on", "turtles", "turtles" ]

apply : Array (element -> mappedElement) -> Array element -> Array mappedElement

Apply a given Array of changes to all elements. If one Array is longer, its extra elements are not used.

import Array exposing (fromList, repeat)

repeat 5 100
    |> apply
        (fromList
            [ \x -> -x, identity, (+) 10 ]
        )
--> fromList [ -100, 100, 110 ]

map2 : (a -> b -> combined) -> Array a -> Array b -> Array combined

Combine the elements of two Arrays with a given function. If one Array is longer, its extra elements are not used.

import Array exposing (fromList)

map2 (\a b -> a + b)
    (fromList [ 1, 2, 3 ])
    (fromList [ 1, 2, 3, 4 ])
--> fromList [ 2, 4, 6 ]

map2 Tuple.pair
    (fromList [ 1, 2, 3 ])
    (fromList [ 'a', 'b' ])
--> fromList [ ( 1, 'a' ), ( 2, 'b' ) ]

Note: zip can be used instead of map2 Tuple.pair.

map3 : (a -> b -> c -> combined) -> Array a -> Array b -> Array c -> Array combined

Combine the elements of three Arrays with the given function. See map2.

Note: zip3 can be used instead of map3 (\a b c -> ( a, b, c )).

map4 : (a -> b -> c -> d -> combined) -> Array a -> Array b -> Array c -> Array d -> Array combined

Combine the elements of four Arrays with the given function. See map2.

map5 : (a -> b -> c -> d -> e -> combined) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array combined

Combine the elements of five Arrays with the given function. See map2.

zip : Array firstElement -> Array secondElement -> Array ( firstElement, secondElement )

Combine the elements of two Arrays into tuples. If one is longer, its extra elements are not used.

import Array exposing (fromList)

zip
    (fromList [ 1, 2, 3 ])
    (fromList [ 'a', 'b' ])
--> fromList [ ( 1, 'a' ), ( 2, 'b' ) ]

zip3 : Array firstElement -> Array secondElement -> Array thirdElement -> Array ( firstElement, secondElement, thirdElement )

Zip the elements of three Arrays into 3-tuples. Only the indexes of the shortest Array are used.

import Array exposing (fromList)

zip3
    (fromList [ 1, 2, 3 ])
    (fromList [ 'a', 'b' ])
    (fromList [ "a", "b", "c", "d" ])
--> fromList
-->     [ ( 1, 'a', "a" )
-->     , ( 2, 'b', "b" )
-->     ]

unzip : Array ( elementFirst, elementSecond ) -> ( Array elementFirst, Array elementSecond )

Split all tuple elements into a tuple of one Array with the first and one with the second values.

import Array exposing (fromList)

unzip
    (fromList
        [ ( 1, 'a' ), ( 2, 'b' ), ( 3, 'c' ) ]
    )
--> ( fromList [ 1, 2, 3 ]
--> , fromList [ 'a', 'b', 'c' ]
--> )

resize

resizelRepeat : Basics.Int -> element -> Array element -> Array element

Resize from the left, padding the right-hand side with a given value.

import Array exposing (fromList, empty)

fromList [ 1, 2 ] |> resizelRepeat 4 0
--> fromList [ 1, 2, 0, 0 ]

fromList [ 1, 2, 3 ] |> resizelRepeat 2 0
--> fromList [ 1, 2 ]

fromList [ 1, 2 ] |> resizelRepeat -1 0
--> empty

resizerRepeat : Basics.Int -> element -> Array element -> Array element

Resize from the right, padding the left-hand side with a given value.

import Array exposing (fromList, empty)

fromList [ 1, 2 ] |> resizerRepeat 4 0
--> fromList [ 0, 0, 1, 2 ]

fromList [ 1, 2, 3 ] |> resizerRepeat 2 0
--> fromList [ 2, 3 ]

fromList [ 1, 2 ] |> resizerRepeat -1 0
--> empty

resizelIndexed : Basics.Int -> (Basics.Int -> element) -> Array element -> Array element

Resize from the left, padding the right-hand side with a given value based on index.

import Array exposing (fromList, empty)

fromList [ 'a', 'b', 'c' ]
    |> resizelIndexed 5 toLetterInAlphabet
--> fromList [ 'a', 'b', 'c', 'd', 'e' ]

fromList [ 'a', 'b', 'c' ]
    |> resizelIndexed 2 toLetterInAlphabet
--> fromList [ 'a', 'b' ]

fromList [ 'a', 'b', 'c' ]
    |> resizelIndexed -1 toLetterInAlphabet
--> empty

toLetterInAlphabet : Int -> Char
toLetterInAlphabet inAlphabet =
    ('a' |> Char.toCode) + inAlphabet
        |> Char.fromCode

resizerIndexed : Basics.Int -> (Basics.Int -> element) -> Array element -> Array element

Resize from the right, padding the left-hand side with a given value based on index.

import Array exposing (fromList, empty)

fromList [ 10, 25, 36 ]
    |> resizerIndexed 5 (\n -> n * 5)
--> fromList [ 0, 5, 10, 25, 36 ]

fromList [ 10, 25, 36 ]
    |> resizerIndexed 2 (\n -> n * 5)
--> fromList [ 25, 36 ]

fromList [ 10, 25, 36 ]
    |> resizerIndexed -1 (\n -> n * 5)
--> empty

transform

mapToList : (element -> mappedElement) -> Array element -> List mappedElement

Apply a function to the elements in the array and collect the result in a List.

import Array exposing (fromList)
import Html

fromList [ "a", "b", "c" ]
    |> mapToList Html.text
--> [ Html.text "a", Html.text "b", Html.text "c" ]

indexedMapToList : (Basics.Int -> element -> mappedElement) -> Array element -> List mappedElement

Transform all elements with their indexes as the first argument and collect the result in a List.

import Array exposing (Array, fromList)
import Html exposing (Html)

type alias Exercise =
    { name : String }

exerciseRender : Int -> Exercise -> Html msg
exerciseRender index =
    \exercise ->
        String.concat
            [ "Exercise #"
            , String.fromInt (index + 1)
            , " - "
            , exercise.name
            ]
            |> Html.text

exercisesRender : Array Exercise -> Html msg
exercisesRender =
    indexedMapToList renderExercise
        >> Html.div []