Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gatherEquals function. #114

Merged
merged 9 commits into from
Oct 8, 2018
Merged
57 changes: 54 additions & 3 deletions src/List/Extra.elm
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ module List.Extra exposing
, intercalate, transpose, subsequences, permutations, interweave, cartesianProduct
, foldl1, foldr1, indexedFoldl, indexedFoldr
, scanl, scanl1, scanr, scanr1, mapAccuml, mapAccumr, unfoldr, iterate, initialize, cycle
, splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, select, selectSplit
, splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith
, isPrefixOf, isSuffixOf, isInfixOf, isSubsequenceOf, isPermutationOf
, notMember, find, elemIndex, elemIndices, findIndex, findIndices, count
, zip, zip3
, lift2, lift3, lift4
, groupsOf, groupsOfWithStep, groupsOfVarying, greedyGroupsOf, greedyGroupsOfWithStep
)

{-| Convenience functions for working with List


Expand All @@ -36,7 +36,7 @@ module List.Extra exposing

# Sublists

@docs splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, select, selectSplit
@docs splitAt, splitWhen, takeWhileRight, dropWhileRight, span, break, stripPrefix, group, groupWhile, inits, tails, select, selectSplit, gatherEquals, gatherEqualsBy, gatherWith


# Predicates
Expand Down Expand Up @@ -1857,3 +1857,54 @@ greedyGroupsOfWithStep size step xs =

else
[]

{-| Group equal elements together. This is different from `group` as each sublist
will contain *all* equal elements of the original list. Elements will be grouped
in the same order as they appear in the original list. The same applies to elements
within each group.

gatherEquals [1,2,1,3,2]
--> [(1,[1]),(2,[2]),(3,[])]
-}
gatherEquals : List a -> List (a, List a)
gatherEquals list =
gatherWith (==) list


{-| Group equal elements together. A function is applied to each element of the list
and then the equality check is performed against the results of that function evaluation.
Elements will be grouped in the same order as they appear in the original list. The
same applies to elements within each group.

gatherEqualsBy .age [{age=25},{age=23},{age=25}]
--> [({age=25},[{age=25}]),({age=23},[])]
-}
gatherEqualsBy : (a -> b) -> List a -> List (a, List a)
gatherEqualsBy extract list =
gatherWith (\a b -> (extract a) == (extract b)) list


{-| Group equal elements together using a custom equality function. Elements will be
grouped in the same order as they appear in the original list. The same applies to
elements within each group.

gatherWith (==) [1,2,1,3,2]
--> [(1,[1]),(2,[2]),(3,[])]
-}
gatherWith : (a -> a -> Bool) -> List a -> List (a, List a)
gatherWith testFn list =
let
helper : List a -> List (a,List a) -> List (a, List a)
helper scattered gathered =
case scattered of
[] ->
List.reverse gathered

toGather :: population ->
let
( gathering, remaining ) =
List.partition (testFn toGather) population
in
helper remaining <| (toGather, gathering) :: gathered
in
helper list []
57 changes: 57 additions & 0 deletions tests/Tests.elm
Original file line number Diff line number Diff line change
Expand Up @@ -685,4 +685,61 @@ all =
\() ->
Expect.equal (setIf (\x -> modBy 2 x == 0) 0 [ 17, 8, 2, 9 ]) [ 17, 0, 0, 9 ]
]
, describe "gatherEquals"
[ test "empty list" <|
\() ->
gatherEquals []
|> Expect.equal []
, test "single element" <|
\() ->
gatherEquals [ 1 ]
|> Expect.equal [ (1, []) ]
, test "proper test" <|
\() ->
gatherEquals [ 1, 2, 1, 2, 3, 4, 1 ]
|> Expect.equal
[ ( 1, [ 1, 1 ])
, ( 2, [ 2 ])
, ( 3, [])
, ( 4, [])
]
]
, describe "gatherEqualsBy"
[ test "empty list" <|
\() ->
gatherEqualsBy identity []
|> Expect.equal []
, test "single element" <|
\() ->
gatherEqualsBy identity [ 1 ]
|> Expect.equal [ (1, []) ]
, test "proper test" <|
\() ->
gatherEqualsBy identity [ 1, 2, 1, 2, 3, 4, 1 ]
|> Expect.equal
[ ( 1, [ 1, 1 ])
, ( 2, [ 2 ])
, ( 3, [])
, ( 4, [])
]
]
, describe "gatherWith"
[ test "empty list" <|
\() ->
gatherWith (==) []
|> Expect.equal []
, test "single element" <|
\() ->
gatherWith (==) [ 1 ]
|> Expect.equal [ (1, []) ]
, test "proper test" <|
\() ->
gatherWith (==) [ 1, 2, 1, 2, 3, 4, 1 ]
|> Expect.equal
[ ( 1, [ 1, 1 ])
, ( 2, [ 2 ])
, ( 3, [])
, ( 4, [])
]
]
]