Skip to content

Commit b085256

Browse files
matthewleonkritzcreek
authored andcommitted
use ordering for nubBy
The old `nubBy` becomes `nubByEq`, which only requires an equality relation.
1 parent b649cef commit b085256

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

src/Data/Array.purs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ module Data.Array
9292
, nub
9393
, nubEq
9494
, nubBy
95+
, nubByEq
9596
, union
9697
, unionBy
9798
, delete
@@ -879,41 +880,55 @@ groupBy op xs =
879880
-- | ```
880881
-- |
881882
nub :: forall a. Ord a => Array a -> Array a
882-
nub arr = case head indexedAndSorted of
883-
Nothing -> []
884-
Just x -> map fst $ sortWith snd $ pureST do
885-
-- TODO: use NonEmptyArrays here to avoid partial functions
886-
result <- unsafeThaw $ singleton x
887-
foreachE indexedAndSorted \pair@(Tuple x' i) -> do
888-
lst <- fst <<< unsafePartial (fromJust <<< last) <$> unsafeFreeze result
889-
when (lst /= x') $ void $ pushSTArray result pair
890-
unsafeFreeze result
891-
892-
where
893-
indexedAndSorted = sort $ mapWithIndex (flip Tuple) arr
883+
nub = nubBy compare
894884

895885
-- | Remove the duplicates from an array, creating a new array.
896886
-- |
897887
-- | This less efficient version of `nub` only requires an `Eq` instance.
898888
-- |
899889
-- | ```purescript
900-
-- | nub [1, 2, 1, 3, 3] = [1, 2, 3]
890+
-- | nubEq [1, 2, 1, 3, 3] = [1, 2, 3]
901891
-- | ```
902892
-- |
903893
nubEq :: forall a. Eq a => Array a -> Array a
904-
nubEq = nubBy eq
894+
nubEq = nubByEq eq
895+
896+
-- | Remove the duplicates from an array, where element equality is determined
897+
-- | by the specified ordering, creating a new array.
898+
-- |
899+
-- | ```purescript
900+
-- | nubBy compare [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
901+
-- | ```
902+
-- |
903+
nubBy :: forall a. (a -> a -> Ordering) -> Array a -> Array a
904+
nubBy comp xs = case head indexedAndSorted of
905+
Nothing -> []
906+
Just x -> map snd $ sortWith fst $ pureST do
907+
-- TODO: use NonEmptyArrays here to avoid partial functions
908+
result <- unsafeThaw $ singleton x
909+
foreachE indexedAndSorted \pair@(Tuple i x') -> do
910+
lst <- snd <<< unsafePartial (fromJust <<< last) <$> unsafeFreeze result
911+
when (comp lst x' /= EQ) $ void $ pushSTArray result pair
912+
unsafeFreeze result
913+
where
914+
indexedAndSorted :: Array (Tuple Int a)
915+
indexedAndSorted = sortBy (\x y -> comp (snd x) (snd y))
916+
(mapWithIndex Tuple xs)
905917

906918
-- | Remove the duplicates from an array, where element equality is determined
907919
-- | by the specified equivalence relation, creating a new array.
908920
-- |
921+
-- | This less efficient version of `nubBy` only requires an equivalence
922+
-- | relation.
923+
-- |
909924
-- | ```purescript
910-
-- | nubBy (\a b -> a `mod` 3 == b `mod` 3) [1, 3, 4, 5, 6] = [1,3,5]
925+
-- | nubByEq (\a b -> a `mod` 3 == b `mod` 3) [1, 3, 4, 5, 6] = [1,3,5]
911926
-- | ```
912927
-- |
913-
nubBy :: forall a. (a -> a -> Boolean) -> Array a -> Array a
914-
nubBy eq xs =
928+
nubByEq :: forall a. (a -> a -> Boolean) -> Array a -> Array a
929+
nubByEq eq xs =
915930
case uncons xs of
916-
Just o -> o.head : nubBy eq (filter (\y -> not (o.head `eq` y)) o.tail)
931+
Just o -> o.head : nubByEq eq (filter (\y -> not (o.head `eq` y)) o.tail)
917932
Nothing -> []
918933

919934
-- | Calculate the union of two arrays. Note that duplicates in the first array
@@ -938,7 +953,7 @@ union = unionBy (==)
938953
-- | ```
939954
-- |
940955
unionBy :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Array a
941-
unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubBy eq ys) xs
956+
unionBy eq xs ys = xs <> foldl (flip (deleteBy eq)) (nubByEq eq ys) xs
942957

943958
-- | Delete the first element of an array which is equal to the specified value,
944959
-- | creating a new array.

test/Test/Data/Array.purs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,11 @@ testArray = do
319319
assert $ A.nubEq [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
320320

321321
log "nubBy should remove duplicate items from the list using a supplied predicate"
322+
assert $ A.nubBy compare [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
323+
324+
log "nubByEq should remove duplicate items from the list using a supplied predicate"
322325
let nubPred = \x y -> if odd x then false else x == y
323-
assert $ A.nubBy nubPred [1, 2, 2, 3, 3, 4, 4, 1] == [1, 2, 3, 3, 4, 1]
326+
assert $ A.nubByEq nubPred [1, 2, 2, 3, 3, 4, 4, 1] == [1, 2, 3, 3, 4, 1]
324327

325328
log "union should produce the union of two arrays"
326329
assert $ A.union [1, 2, 3] [2, 3, 4] == [1, 2, 3, 4]

0 commit comments

Comments
 (0)