Skip to content

Commit 6687768

Browse files
authored
Add List.Extra.takeRight and dropRight (#90)
* Add List.Extra.takeRight and dropRight * Split takeWhileRight and dropWhileRight test groups * Add benchmarks
1 parent 6751e94 commit 6687768

File tree

5 files changed

+201
-3
lines changed

5 files changed

+201
-3
lines changed

benchmarks/src/Benchmarks.elm

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ import Benchmark exposing (Benchmark, describe)
1818
import Benchmark.Alternative exposing (rank)
1919
import Benchmark.Runner.Alternative as BenchmarkRunner
2020
import List.Extra
21+
import List.Extra.DropRight
2122
import List.Extra.GroupsOf
2223
import List.Extra.Lift
2324
import List.Extra.NotMember
25+
import List.Extra.TakeRight
2426
import List.Extra.Unfoldr
2527
import List.Extra.UniquePairs
2628
import Maybe.Extra.AndMap
@@ -192,6 +194,9 @@ listExtra =
192194

193195
intList =
194196
List.range 1 100
197+
198+
longList =
199+
List.range 1 1000
195200
in
196201
describe "List.Extra"
197202
([ rank "uniquePairs"
@@ -234,6 +239,42 @@ listExtra =
234239
[ ( "Original", List.Extra.NotMember.notMemberOriginal )
235240
, ( "Simplified", List.Extra.NotMember.notMemberSimple )
236241
]
242+
, rank "dropRight 5 10"
243+
(\dropRight -> dropRight 5 shortList)
244+
[ ( "foldr", List.Extra.DropRight.dropRightFoldr )
245+
, ( "reverse", List.Extra.DropRight.dropRightReverse )
246+
, ( "length", List.Extra.DropRight.dropRightLength )
247+
]
248+
, rank "takeRight 5 10"
249+
(\takeRight -> takeRight 5 shortList)
250+
[ ( "foldr", List.Extra.TakeRight.takeRightFoldr )
251+
, ( "reverse", List.Extra.TakeRight.takeRightReverse )
252+
, ( "length", List.Extra.TakeRight.takeRightLength )
253+
]
254+
, rank "dropRight 50 100"
255+
(\dropRight -> dropRight 50 intList)
256+
[ ( "foldr", List.Extra.DropRight.dropRightFoldr )
257+
, ( "reverse", List.Extra.DropRight.dropRightReverse )
258+
, ( "length", List.Extra.DropRight.dropRightLength )
259+
]
260+
, rank "takeRight 50 100"
261+
(\takeRight -> takeRight 50 intList)
262+
[ ( "foldr", List.Extra.TakeRight.takeRightFoldr )
263+
, ( "reverse", List.Extra.TakeRight.takeRightReverse )
264+
, ( "length", List.Extra.TakeRight.takeRightLength )
265+
]
266+
, rank "dropRight 500 1000"
267+
(\dropRight -> dropRight 500 longList)
268+
[ ( "foldr", List.Extra.DropRight.dropRightFoldr )
269+
, ( "reverse", List.Extra.DropRight.dropRightReverse )
270+
, ( "length", List.Extra.DropRight.dropRightLength )
271+
]
272+
, rank "takeRight 500 1000"
273+
(\takeRight -> takeRight 500 longList)
274+
[ ( "foldr", List.Extra.TakeRight.takeRightFoldr )
275+
, ( "reverse", List.Extra.TakeRight.takeRightReverse )
276+
, ( "length", List.Extra.TakeRight.takeRightLength )
277+
]
237278
]
238279
++ List.concatMap toComparisonsGroupsOfWithStep (List.range 1 4)
239280
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module List.Extra.DropRight exposing
2+
( dropRightFoldr
3+
, dropRightLength
4+
, dropRightReverse
5+
)
6+
7+
8+
dropRightFoldr : Int -> List a -> List a
9+
dropRightFoldr n lst =
10+
let
11+
step x ( n_, acc ) =
12+
if n_ > 0 then
13+
( n_ - 1, acc )
14+
15+
else
16+
( 0, x :: acc )
17+
in
18+
List.foldr step ( n, [] ) lst
19+
|> Tuple.second
20+
21+
22+
dropRightReverse : Int -> List a -> List a
23+
dropRightReverse n lst =
24+
lst
25+
|> List.reverse
26+
|> List.drop n
27+
|> List.reverse
28+
29+
30+
dropRightLength : Int -> List a -> List a
31+
dropRightLength n lst =
32+
lst |> List.take (List.length lst - n)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module List.Extra.TakeRight exposing
2+
( takeRightFoldr
3+
, takeRightLength
4+
, takeRightReverse
5+
)
6+
7+
8+
takeRightFoldr : Int -> List a -> List a
9+
takeRightFoldr n lst =
10+
let
11+
step x ( n_, acc ) =
12+
if n_ > 0 then
13+
( n_ - 1, x :: acc )
14+
15+
else
16+
-- Wish we could stop here. List.Extra.stoppableFoldr where are you?
17+
( 0, acc )
18+
in
19+
List.foldr step ( n, [] ) lst
20+
|> Tuple.second
21+
22+
23+
takeRightReverse : Int -> List a -> List a
24+
takeRightReverse n lst =
25+
lst
26+
|> List.reverse
27+
|> List.take n
28+
|> List.reverse
29+
30+
31+
takeRightLength : Int -> List a -> List a
32+
takeRightLength n lst =
33+
lst |> List.drop (List.length lst - n)

src/List/Extra.elm

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module List.Extra exposing
33
, intercalate, transpose, subsequences, permutations, interweave, cartesianProduct, uniquePairs
44
, foldl1, foldr1, indexedFoldl, indexedFoldr, Step(..), stoppableFoldl
55
, scanl, scanl1, scanr, scanr1, mapAccuml, mapAccumr, unfoldr, iterate, initialize, cycle, reverseRange
6-
, splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, conditional, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith, subsequencesNonEmpty, frequencies
6+
, splitAt, splitWhen, takeRight, dropRight, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, conditional, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith, subsequencesNonEmpty, frequencies
77
, isPrefixOf, isSuffixOf, isInfixOf, isSubsequenceOf, isPermutationOf
88
, notMember, find, elemIndex, elemIndices, findIndex, findIndices, findMap, count
99
, zip, zip3
@@ -37,7 +37,7 @@ module List.Extra exposing
3737
3838
# Sublists
3939
40-
@docs splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, conditional, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith, subsequencesNonEmpty, frequencies
40+
@docs splitAt, splitWhen, takeRight, dropRight, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, conditional, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith, subsequencesNonEmpty, frequencies
4141
4242
4343
# Predicates
@@ -1592,6 +1592,32 @@ splitWhen predicate list =
15921592
|> Maybe.map (\i -> splitAt i list)
15931593

15941594

1595+
{-| Take the last _n_ members of a list.
1596+
1597+
take 2 [ 1, 2, 3, 4, 5 ] == [ 1, 2 ]
1598+
1599+
-}
1600+
takeRight : Int -> List a -> List a
1601+
takeRight n lst =
1602+
lst
1603+
|> List.reverse
1604+
|> List.take n
1605+
|> List.reverse
1606+
1607+
1608+
{-| Drop the last _n_ members of a list.
1609+
1610+
dropRight 2 [ 1, 2, 3, 4, 5 ] == [ 1, 2, 3 ]
1611+
1612+
-}
1613+
dropRight : Int -> List a -> List a
1614+
dropRight n lst =
1615+
lst
1616+
|> List.reverse
1617+
|> List.drop n
1618+
|> List.reverse
1619+
1620+
15951621
{-| Take elements from the right, while predicate still holds.
15961622
15971623
takeWhileRight ((<) 5) (List.range 1 10)

tests/ListTests.elm

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,77 @@ all =
468468
\() ->
469469
Expect.equal (List.Extra.splitWhen (\n -> n == 6) [ 1, 2, 3, 4, 5 ]) Nothing
470470
]
471+
, describe "takeRight" <|
472+
[ test "keeps the correct items" <|
473+
\() ->
474+
List.Extra.takeRight 3 (List.range 1 5)
475+
|> Expect.equal [ 3, 4, 5 ]
476+
, fuzz2 (Fuzz.int |> Fuzz.map (\n -> -(abs n))) (Fuzz.list Fuzz.int) "non-positive number of items" <|
477+
\negativeN list ->
478+
List.Extra.takeRight negativeN list
479+
|> Expect.equalLists []
480+
, fuzz2 (Fuzz.intRange 0 10) (Fuzz.list Fuzz.int) "taking more than there is" <|
481+
\add list ->
482+
List.Extra.takeRight (List.length list + add) list
483+
|> Expect.equalLists list
484+
, fuzz (Fuzz.listOfLengthBetween 1 5 Fuzz.int) "taking last item" <|
485+
\list ->
486+
case List.Extra.last list of
487+
Nothing ->
488+
Debug.todo "fuzzer bug?"
489+
490+
Just last ->
491+
List.Extra.takeRight 1 list
492+
|> Expect.equalLists [ last ]
493+
, fuzz (Fuzz.listOfLengthBetween 1 5 Fuzz.int) "taking all but first item" <|
494+
\list ->
495+
case List.tail list of
496+
Nothing ->
497+
Debug.todo "fuzzer bug?"
498+
499+
Just butFirst ->
500+
List.Extra.takeRight (List.length list - 1) list
501+
|> Expect.equalLists butFirst
502+
]
503+
, describe "dropRight" <|
504+
[ test "drops the correct items" <|
505+
\() ->
506+
List.Extra.dropRight 3 (List.range 1 5)
507+
|> Expect.equal [ 1, 2 ]
508+
, fuzz2 (Fuzz.int |> Fuzz.map (\n -> -(abs n))) (Fuzz.list Fuzz.int) "non-positive number of items" <|
509+
\negativeN list ->
510+
List.Extra.dropRight negativeN list
511+
|> Expect.equalLists list
512+
, fuzz2 (Fuzz.intRange 0 10) (Fuzz.list Fuzz.int) "dropping more than there is" <|
513+
\add list ->
514+
List.Extra.dropRight (List.length list + add) list
515+
|> Expect.equalLists []
516+
, fuzz (Fuzz.listOfLengthBetween 1 5 Fuzz.int) "dropping last item" <|
517+
\list ->
518+
case List.Extra.init list of
519+
Nothing ->
520+
Debug.todo "fuzzer bug?"
521+
522+
Just init ->
523+
List.Extra.dropRight 1 list
524+
|> Expect.equalLists init
525+
, fuzz (Fuzz.listOfLengthBetween 1 5 Fuzz.int) "dropping all but first item" <|
526+
\list ->
527+
case List.head list of
528+
Nothing ->
529+
Debug.todo "fuzzer bug?"
530+
531+
Just first ->
532+
List.Extra.dropRight (List.length list - 1) list
533+
|> Expect.equalLists [ first ]
534+
]
471535
, describe "takeWhileRight" <|
472536
[ test "keeps the correct items" <|
473537
\() ->
474538
Expect.equal (List.Extra.takeWhileRight (\x -> 5 < x) (List.range 1 10)) [ 6, 7, 8, 9, 10 ]
475-
, test "drops the correct items" <|
539+
]
540+
, describe "dropWhileRight" <|
541+
[ test "drops the correct items" <|
476542
\() ->
477543
Expect.equal (List.Extra.dropWhileRight (\x -> 5 < x) (List.range 1 10)) [ 1, 2, 3, 4, 5 ]
478544
]

0 commit comments

Comments
 (0)