Skip to content

Commit 72e4b24

Browse files
authored
Add splitAt (#179)
* Add `splitAt` * Make `splitAt` return a record instead of a tuple * Add test case and example for `splitAt` with an empty array
1 parent 603c332 commit 72e4b24

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

src/Data/Array.purs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ module Data.Array
6969
, concatMap
7070
, filter
7171
, partition
72+
, splitAt
7273
, filterA
7374
, mapMaybe
7475
, catMaybes
@@ -602,6 +603,27 @@ foreign import partition
602603
-> Array a
603604
-> { yes :: Array a, no :: Array a }
604605

606+
-- | Splits an array into two subarrays, where `before` contains the elements
607+
-- | up to (but not including) the given index, and `after` contains the rest
608+
-- | of the elements, from that index on.
609+
-- |
610+
-- | ```purescript
611+
-- | >>> splitAt 3 [1, 2, 3, 4, 5]
612+
-- | { before: [1, 2, 3], after: [4, 5] }
613+
-- | ```
614+
-- |
615+
-- | Thus, the length of `(splitAt i arr).before` will equal either `i` or
616+
-- | `length arr`, if that is shorter. (Or if `i` is negative the length will
617+
-- | be 0.)
618+
-- |
619+
-- | ```purescript
620+
-- | splitAt 2 ([] :: Array Int) == { before: [], after: [] }
621+
-- | splitAt 3 [1, 2, 3, 4, 5] == { before: [1, 2, 3], after: [4, 5] }
622+
-- | ```
623+
splitAt :: forall a. Int -> Array a -> { before :: Array a, after :: Array a }
624+
splitAt i xs | i <= 0 = { before: [], after: xs }
625+
splitAt i xs = { before: slice 0 i xs, after: slice i (length xs) xs }
626+
605627
-- | Filter where the predicate returns a `Boolean` in some `Applicative`.
606628
-- |
607629
-- | ```purescript

src/Data/Array/NonEmpty.purs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ module Data.Array.NonEmpty
4848
, concat
4949
, concatMap
5050
, filter
51+
, splitAt
5152
, partition
5253
, filterA
5354
, mapMaybe
@@ -296,6 +297,9 @@ filterA
296297
-> f (Array a)
297298
filterA f = adaptAny $ A.filterA f
298299

300+
splitAt :: forall a. Int -> NonEmptyArray a -> { before :: Array a, after :: Array a }
301+
splitAt i xs = A.splitAt i $ toArray xs
302+
299303
mapMaybe :: forall a b. (a -> Maybe b) -> NonEmptyArray a -> Array b
300304
mapMaybe f = adaptAny $ A.mapMaybe f
301305

test/Test/Data/Array.purs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,15 @@ testArray = do
202202
log "filter should remove items that don't match a predicate"
203203
assert $ A.filter odd (A.range 0 10) == [1, 3, 5, 7, 9]
204204

205+
log "splitAt should split the array at the given number of elements"
206+
assert $ A.splitAt 2 ([] :: Array Int) == { before: [], after: [] }
207+
assert $ A.splitAt 3 [1, 2, 3, 4, 5] == { before: [1, 2, 3], after: [4, 5] }
208+
assert $ A.splitAt 1 [1, 2, 3] == { before: [1], after: [2, 3] }
209+
assert $ A.splitAt 3 [1, 2, 3] == { before: [1, 2, 3], after: [] }
210+
assert $ A.splitAt 4 [1, 2, 3] == { before: [1, 2, 3], after: [] }
211+
assert $ A.splitAt 0 [1, 2, 3] == { before: [], after: [1, 2, 3] }
212+
assert $ A.splitAt (-1) [1, 2, 3] == { before: [], after: [1, 2, 3] }
213+
205214
log "filterA should remove items that don't match a predicate while using an applicative behaviour"
206215
assert $ A.filterA (Just <<< odd) (A.range 0 10) == Just [1, 3, 5, 7, 9]
207216
assert $ A.filterA (const Nothing) (A.range 0 10) == Nothing

test/Test/Data/Array/NonEmpty.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ testNonEmptyArray = do
166166
log "filter should remove items that don't match a predicate"
167167
assert $ NEA.filter odd (NEA.range 0 10) == [1, 3, 5, 7, 9]
168168

169+
log "splitAt should split the array at the given number of elements"
170+
assert $ NEA.splitAt 3 (fromArray [1, 2, 3, 4, 5]) == { before: [1, 2, 3], after: [4, 5] }
171+
assert $ NEA.splitAt 1 (fromArray [1, 2, 3]) == { before: [1], after: [2, 3] }
172+
assert $ NEA.splitAt 3 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] }
173+
assert $ NEA.splitAt 4 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] }
174+
assert $ NEA.splitAt 0 (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] }
175+
assert $ NEA.splitAt (-1) (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] }
176+
169177
log "filterA should remove items that don't match a predicate while using an applicative behaviour"
170178
assert $ NEA.filterA (Just <<< odd) (NEA.range 0 10) == Just [1, 3, 5, 7, 9]
171179
assert $ NEA.filterA (const Nothing) (NEA.range 0 10) == Nothing

0 commit comments

Comments
 (0)