diff --git a/src/Array/NonEmpty.elm b/src/Array/NonEmpty.elm index ddb1c3f..111db33 100644 --- a/src/Array/NonEmpty.elm +++ b/src/Array/NonEmpty.elm @@ -12,9 +12,11 @@ module Array.NonEmpty , getFirst , getSelected , indexedMap + , indexedMapSelected , initialize , length , map + , mapSelected , push , removeAt , removeAtSafe @@ -62,7 +64,7 @@ Most functions (like `map`) keep the currently selected index untouched, other f # Selected Index -@docs selectedIndex, setSelectedIndex, setSelectedIndexAndReport, getSelected, updateSelected +@docs selectedIndex, setSelectedIndex, setSelectedIndexAndReport, getSelected, updateSelected, mapSelected, indexedMapSelected # Conversions @@ -568,6 +570,52 @@ indexedMap function (NEA first selected rest) = NEA newFirst selected newRest +{-| Apply different functions to every element in an array depending on whether +the element is selected or not. + + Just <| + (repeat 5 1 + |> mapSelected (\isSelected -> + if isSelected then + (*) 2 + else + Basics.identity + )) + --> fromList [2, 1, 1, 1, 1] + +-} +mapSelected : (Bool -> a -> b) -> NonEmptyArray a -> NonEmptyArray b +mapSelected function array = + let + innerFn index = + function (index == selectedIndex array) + in + indexedMap innerFn array + + +{-| Apply different functions to every element with its index as first argument +depending on whether the element is selected or not. + + Just <| + (repeat 5 1 + |> indexedMapSelected (\isSelected -> + if isSelected then + (*) + else + (+) + )) + --> fromList [0, 2, 3, 4, 5] + +-} +indexedMapSelected : (Bool -> Int -> a -> b) -> NonEmptyArray a -> NonEmptyArray b +indexedMapSelected function array = + let + innerFn index = + function (index == selectedIndex array) index + in + indexedMap innerFn array + + {-| Append two arrays to a new one. Just (append (repeat 2 42) (repeat 3 81)) --> fromList [42, 42, 81, 81, 81] diff --git a/tests/NonEmptyArrayTest.elm b/tests/NonEmptyArrayTest.elm index 41654ce..b482af3 100644 --- a/tests/NonEmptyArrayTest.elm +++ b/tests/NonEmptyArrayTest.elm @@ -4,7 +4,6 @@ import Array.Hamt as Array exposing (Array) import Array.NonEmpty as NEA exposing (NonEmptyArray) import Expect exposing (Expectation) import Fuzz exposing (Fuzzer) -import Random import Test exposing (..) @@ -908,6 +907,51 @@ suite = , Expect.equal Nothing (NEA.get 3 nea) ] ] + , describe "mapSelected" + [ test "mapping over a single element" <| + \_ -> + let + nea = + NEA.fromElement 1 + |> NEA.mapSelected addFiveOrMultiplyTwo + in + Expect.equal 6 (NEA.getFirst nea) + , test "mapping over multiple elements" <| + \_ -> + let + mnea = + NEA.fromList [ 1, 2, 3, 4 ] + |> Maybe.map (NEA.mapSelected addFiveOrMultiplyTwo) + in + expectMaybe + (\nea -> + expectAll + [ Expect.equal 4 (NEA.length nea) + , Expect.equal (Just 6) (NEA.get 0 nea) + , Expect.equal (Just 4) (NEA.get 1 nea) + , Expect.equal (Just 6) (NEA.get 2 nea) + , Expect.equal (Just 8) (NEA.get 3 nea) + , Expect.equal Nothing (NEA.get 4 nea) + ] + ) + mnea + ] + , describe "indexedMapSelected" + [ test "indexedMapSelected over multiple elements" <| + \_ -> + let + nea = + NEA.initialize 3 identity + |> NEA.indexedMapSelected multiplyOrAdd + in + expectAll + [ Expect.equal 3 (NEA.length nea) + , Expect.equal (Just 0) (NEA.get 0 nea) + , Expect.equal (Just 2) (NEA.get 1 nea) + , Expect.equal (Just 4) (NEA.get 2 nea) + , Expect.equal Nothing (NEA.get 3 nea) + ] + ] , describe "filter" [ test "filter to zero elements returns Nothing" <| \_ -> @@ -1353,6 +1397,14 @@ suite = ] +addFiveOrMultiplyTwo : Bool -> Int -> Int +addFiveOrMultiplyTwo isSelected = + if isSelected then + (+) 5 + else + (*) 2 + + expectJust : Maybe (NonEmptyArray a) -> Expectation expectJust maybe = case maybe of @@ -1399,6 +1451,14 @@ intList = Fuzz.list (Fuzz.intRange 0 1000) +multiplyOrAdd : Bool -> Int -> Int -> Int +multiplyOrAdd isSelected = + if isSelected then + (*) + else + (+) + + nonEmptyIntList : Fuzzer (List Int) nonEmptyIntList = intList