List
operations that can be applied in either Direction
element : ( Linear.Direction, Basics.Int ) -> List element -> Maybe element
Just
the element at the given index in a Direction
import Linear exposing (Direction(..))
[ 0, 1, 2, 3 ]
|> List.Linear.element ( Down, 0 )
--> Just 3
[ 0, 1, 2, 3 ]
|> List.Linear.element ( Up, 2 )
--> Just 2
Nothing
if the index is out of range:
import Linear exposing (Direction(..))
[ 0, 1, 2, 3 ]
|> List.Linear.element ( Up, 5 )
--> Nothing
[ 0, 1, 2, 3 ]
|> List.Linear.element ( Up, -1 )
--> Nothing
If you're using at-operations often, consider using an Array
instead of a List
to get O(log n)
vs. O(n)
random access performance
elementAlter : ( Linear.Direction, Basics.Int ) -> (element -> element) -> List element -> List element
Alter the element at the given index in a Direction
import Linear exposing (Direction(..))
[ 1, 2, 2 ]
|> List.Linear.elementAlter ( Down, 0 )
(\n -> n + 1)
--> [ 1, 2, 3 ]
Do nothing if the index is out of range
import Linear exposing (Direction(..))
[ 0, 1, 2, 3 ]
|> List.Linear.elementAlter ( Up, 4 )
(\n -> n + 1)
--> [ 0, 1, 2, 3 ]
[ 0, 1, 2, 3 ]
|> List.Linear.elementAlter ( Up, -1 )
(\n -> n + 1)
--> [ 0, 1, 2, 3 ]
If you're using at-operations often, consider using an Array
instead of a List
to get O(log n)
vs. O(n)
random access performance
padToAtLeast : Linear.Direction -> Basics.Int -> (Basics.Int -> List element) -> List element -> List element
Pad in a Direction
based on how much it takes to reach at a given length
import Linear exposing (Direction(..))
[ 1, 2 ]
|> List.Linear.padToAtLeast Up
4
(\l -> List.repeat l 0)
--> [ 1, 2, 0, 0 ]
[ 1, 2 ]
|> List.Linear.padToAtLeast Down
4
(\l -> List.repeat l 0)
--> [ 0, 0, 1, 2 ]
To achieve "resize" behavior, use
padToAtLeast direction length
followed by take direction length
[ 1, 2, 3 ]
|> List.Linear.padToAtLeast Up
2
(\l -> List.repeat l 0)
|> List.Linear.take Up 2
--> [ 1, 2 ]
[ 1, 2, 3 ]
|> List.Linear.padToAtLeast Down
2
(\l -> List.repeat l 0)
|> List.Linear.take Down 2
--> [ 2, 3 ]
foldFrom : accumulationValue -> Linear.Direction -> (element -> accumulationValue -> accumulationValue) -> List element -> accumulationValue
Reduce in a Direction
from a given initial accumulated thing
import Linear exposing (Direction(..))
[ 'l', 'i', 'v', 'e' ]
|> List.Linear.foldFrom "" Up String.cons
--> "evil"
[ 'l', 'i', 'v', 'e' ]
|> List.Linear.foldFrom "" Down String.cons
--> "live"
foldUntilCompleteFrom : foldedPartial -> Linear.Direction -> (element -> foldedPartial -> PartialOrComplete foldedPartial foldedComplete) -> List element -> PartialOrComplete foldedPartial foldedComplete
A fold that can stop
→ (Complete
the fold)
early instead of traversing the whole List
-- from lue-bird/elm-partial-or-complete
import PartialOrComplete exposing (PartialOrComplete(..))
import Linear exposing (Direction(..))
[ 2, -1, 4, 8 ]
-- take from the right while not negative
|> List.Linear.foldUntilCompleteFrom []
Down
(\n soFar ->
if n < 0 then
Complete soFar -- stop the fold
else
Partial (n :: soFar)
)
-- even if none are negative
|> PartialOrComplete.value
--> [ 4, 8 ]
If negative elements exist, our foldUntilCompleteFrom
will return
Complete
with the list up to that point exclusive.
If the list only contains non-negative numbers, the result would be
Partial
with the whole list.
To treat both cases the same way, we use value
, one of a few helpers from
PartialOrComplete
Compared to List.Extra.stoppableFoldl
you'll have the extra information about whether the fold completed or not,
as well as the ability to have different Complete
and Partial
types more in the spirit of
"parse, don't validate" (plus both Direction
s available).
mapFoldFrom : accumulationValue -> Linear.Direction -> ({ element : element, folded : accumulationValue } -> { element : mappedElement, folded : accumulationValue }) -> List element -> { mapped : List mappedElement, folded : accumulationValue }
Map each element using information collected from previous steps,
folding in a given Direction
from given initial information.
Both the mapped Array
and the folded information will be returned
You'll often find this under the name "mapAccum"
import Linear exposing (Direction(..))
[ 1, 2, 3 ]
|> List.Linear.mapFoldFrom 0
Down
(\state ->
{ element = state.folded
, folded = state.folded + state.element
}
)
--> { mapped = [ 5, 3, 0 ], folded = 6 }
mapIndexed : Direction -> (Int -> a -> b) -> (List a -> List b)
mapIndexed indexDirection mapAtIndex =
List.Linear.mapFoldFrom 0
indexDirection
(\state ->
{ element = state.element |> mapAtIndex state.folded
, folded = state.folded + 1
}
)
>> .mapped
[ 'h', 'i', 'y', 'o' ]
|> mapIndexed Up Tuple.pair
--> [ ( 0, 'h' ), ( 1, 'i' ), ( 2, 'y' ), ( 3, 'o' ) ]
[ 'h', 'i', 'y', 'o' ]
|> mapIndexed Down Tuple.pair
--> [ ( 3, 'h' ), ( 2, 'i' ), ( 1, 'y' ), ( 0, 'o' ) ]
take : Linear.Direction -> Basics.Int -> List element -> List element
A given number of elements from one side in a Direction
import Linear exposing (Direction(..))
[ 1, 2, 3, 4 ]
|> List.Linear.take Up 2
--> [ 1, 2 ]
[ 1, 2, 3, 4 ]
|> List.Linear.take Down 2
--> [ 3, 4 ]
[]
if the amount of elements to take is negative
import Linear exposing (Direction(..))
[ 1, 2, 3 ]
|> List.Linear.take Up -100
--> []
drop : Linear.Direction -> Basics.Int -> List element -> List element
Remove a given number of elements from one side in a Direction
import Linear exposing (Direction(..))
removeFirst =
List.Linear.drop Up 0
removeLast =
List.Linear.drop Down 0
Nothing is dropped if the amount of elements to drop is negative
import Linear exposing (Direction(..))
[ 1, 2, 3 ]
|> List.Linear.drop Up -1
--> [ 1, 2, 3 ]
toChunksOf : Linear.Direction -> Basics.Int -> List element -> { chunks : List (List element), remainder : List element }
Split into equal-sized chunks
of a given length in a given Direction
The left over elements to one side are in remainder
import Linear exposing (Direction(..))
[ 1, 2, 3, 4, 5, 6, 7 ]
|> List.Linear.toChunksOf Up 3
--> { chunks = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
--> , remainder = [ 7 ]
--> }
[ 1, 2, 3, 4, 5, 6, 7 ]
|> List.Linear.toChunksOf Down 3
--> { remainder = [ 1 ]
--> , chunks = [ [ 2, 3, 4 ], [ 5, 6, 7 ] ]
--> }