diff --git a/src/Data/Array.purs b/src/Data/Array.purs index 0409530e..8a75dd19 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -69,6 +69,7 @@ module Data.Array , concatMap , filter , partition + , splitAt , filterA , mapMaybe , catMaybes @@ -600,6 +601,27 @@ foreign import partition -> Array a -> { yes :: Array a, no :: Array a } +-- | Splits an array into two subarrays, where `before` contains the elements +-- | up to (but not including) the given index, and `after` contains the rest +-- | of the elements, from that index on. +-- | +-- | ```purescript +-- | >>> splitAt 3 [1, 2, 3, 4, 5] +-- | { before: [1, 2, 3], after: [4, 5] } +-- | ``` +-- | +-- | Thus, the length of `(splitAt i arr).before` will equal either `i` or +-- | `length arr`, if that is shorter. (Or if `i` is negative the length will +-- | be 0.) +-- | +-- | ```purescript +-- | splitAt 2 ([] :: Array Int) == { before: [], after: [] } +-- | splitAt 3 [1, 2, 3, 4, 5] == { before: [1, 2, 3], after: [4, 5] } +-- | ``` +splitAt :: forall a. Int -> Array a -> { before :: Array a, after :: Array a } +splitAt i xs | i <= 0 = { before: [], after: xs } +splitAt i xs = { before: slice 0 i xs, after: slice i (length xs) xs } + -- | Filter where the predicate returns a `Boolean` in some `Applicative`. -- | -- | ```purescript diff --git a/src/Data/Array/NonEmpty.purs b/src/Data/Array/NonEmpty.purs index d987fd8f..119b74a9 100644 --- a/src/Data/Array/NonEmpty.purs +++ b/src/Data/Array/NonEmpty.purs @@ -48,6 +48,7 @@ module Data.Array.NonEmpty , concat , concatMap , filter + , splitAt , partition , filterA , mapMaybe @@ -296,6 +297,9 @@ filterA -> f (Array a) filterA f = adaptAny $ A.filterA f +splitAt :: forall a. Int -> NonEmptyArray a -> { before :: Array a, after :: Array a } +splitAt i xs = A.splitAt i $ toArray xs + mapMaybe :: forall a b. (a -> Maybe b) -> NonEmptyArray a -> Array b mapMaybe f = adaptAny $ A.mapMaybe f diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index d1c59f6a..39ff57a8 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -202,6 +202,15 @@ testArray = do log "filter should remove items that don't match a predicate" assert $ A.filter odd (A.range 0 10) == [1, 3, 5, 7, 9] + log "splitAt should split the array at the given number of elements" + assert $ A.splitAt 2 ([] :: Array Int) == { before: [], after: [] } + assert $ A.splitAt 3 [1, 2, 3, 4, 5] == { before: [1, 2, 3], after: [4, 5] } + assert $ A.splitAt 1 [1, 2, 3] == { before: [1], after: [2, 3] } + assert $ A.splitAt 3 [1, 2, 3] == { before: [1, 2, 3], after: [] } + assert $ A.splitAt 4 [1, 2, 3] == { before: [1, 2, 3], after: [] } + assert $ A.splitAt 0 [1, 2, 3] == { before: [], after: [1, 2, 3] } + assert $ A.splitAt (-1) [1, 2, 3] == { before: [], after: [1, 2, 3] } + log "filterA should remove items that don't match a predicate while using an applicative behaviour" assert $ A.filterA (Just <<< odd) (A.range 0 10) == Just [1, 3, 5, 7, 9] assert $ A.filterA (const Nothing) (A.range 0 10) == Nothing diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index fbc576fa..ba791e2b 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -166,6 +166,14 @@ testNonEmptyArray = do log "filter should remove items that don't match a predicate" assert $ NEA.filter odd (NEA.range 0 10) == [1, 3, 5, 7, 9] + log "splitAt should split the array at the given number of elements" + assert $ NEA.splitAt 3 (fromArray [1, 2, 3, 4, 5]) == { before: [1, 2, 3], after: [4, 5] } + assert $ NEA.splitAt 1 (fromArray [1, 2, 3]) == { before: [1], after: [2, 3] } + assert $ NEA.splitAt 3 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] } + assert $ NEA.splitAt 4 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] } + assert $ NEA.splitAt 0 (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] } + assert $ NEA.splitAt (-1) (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] } + log "filterA should remove items that don't match a predicate while using an applicative behaviour" assert $ NEA.filterA (Just <<< odd) (NEA.range 0 10) == Just [1, 3, 5, 7, 9] assert $ NEA.filterA (const Nothing) (NEA.range 0 10) == Nothing