diff --git a/src/Data/Array.purs b/src/Data/Array.purs index ae535298..fd7b503e 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -959,10 +959,10 @@ group xs = groupBy eq xs -- | groupAll [1, 1, 2, 2, 1] == [NonEmptyArray [1, 1, 1], NonEmptyArray [2, 2]] -- | ``` groupAll :: forall a. Ord a => Array a -> Array (NonEmptyArray a) -groupAll = groupAllBy eq +groupAll = groupAllBy compare -- | Deprecated previous name of `groupAll`. -group' :: forall a. Warn (Text "'group\'' is deprecated, use groupAll instead") => Ord a => Array a -> Array (NonEmptyArray a) +group' :: forall a. Warn (Text "'group\'' is deprecated, use 'groupAll' instead") => Ord a => Array a -> Array (NonEmptyArray a) group' = groupAll -- | Group equal, consecutive elements of an array into arrays, using the @@ -987,15 +987,15 @@ groupBy op xs = STA.unsafeFreeze result -- | Group equal elements of an array into arrays, using the specified --- | equivalence relation to determine equality. +-- | comparison function to determine equality. -- | -- | ```purescript --- | groupAllBy (\a b -> odd a && odd b) [1, 3, 2, 4, 3, 3] --- | = [NonEmptyArray [1], NonEmptyArray [2], NonEmptyArray [3, 3, 3], NonEmptyArray [4]] +-- | groupAllBy (comparing Down) [1, 3, 2, 4, 3, 3] +-- | = [NonEmptyArray [4], NonEmptyArray [3, 3, 3], NonEmptyArray [2], NonEmptyArray [1]] -- | ``` -- | -groupAllBy :: forall a. Ord a => (a -> a -> Boolean) -> Array a -> Array (NonEmptyArray a) -groupAllBy p = groupBy p <<< sort +groupAllBy :: forall a. (a -> a -> Ordering) -> Array a -> Array (NonEmptyArray a) +groupAllBy cmp = groupBy (\x y -> cmp x y == EQ) <<< sortBy cmp -- | Remove the duplicates from an array, creating a new array. -- | diff --git a/src/Data/Array/NonEmpty.purs b/src/Data/Array/NonEmpty.purs index 7ba50641..bbc51af8 100644 --- a/src/Data/Array/NonEmpty.purs +++ b/src/Data/Array/NonEmpty.purs @@ -66,8 +66,10 @@ module Data.Array.NonEmpty , dropWhile , span , group + , groupAll , group' , groupBy + , groupAllBy , nub , nubBy @@ -118,6 +120,7 @@ import Data.Tuple (Tuple(..)) import Data.Unfoldable (class Unfoldable) import Data.Unfoldable1 (class Unfoldable1, unfoldr1) import Partial.Unsafe (unsafePartial) +import Prim.TypeError (class Warn, Text) import Unsafe.Coerce (unsafeCoerce) -- | Internal - adapt an Array transform to NonEmptyArray @@ -350,15 +353,49 @@ span -> { init :: Array a, rest :: Array a } span f = adaptAny $ A.span f +-- | Group equal, consecutive elements of an array into arrays. +-- | +-- | ```purescript +-- | group (NonEmptyArray [1, 1, 2, 2, 1]) == +-- | NonEmptyArray [NonEmptyArray [1, 1], NonEmptyArray [2, 2], NonEmptyArray [1]] +-- | ``` group :: forall a. Eq a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) group = unsafeAdapt $ A.group -group' :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) -group' = unsafeAdapt $ A.group' - +-- | Group equal elements of an array into arrays. +-- | +-- | ```purescript +-- | groupAll (NonEmptyArray [1, 1, 2, 2, 1]) == +-- | NonEmptyArray [NonEmptyArray [1, 1, 1], NonEmptyArray [2, 2]] +-- | ` +groupAll :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +groupAll = groupAllBy compare + +-- | Deprecated previous name of `groupAll`. +group' :: forall a. Warn (Text "'group\'' is deprecated, use 'groupAll' instead") => Ord a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +group' = unsafeAdapt $ A.groupAll + +-- | Group equal, consecutive elements of an array into arrays, using the +-- | specified equivalence relation to determine equality. +-- | +-- | ```purescript +-- | groupBy (\a b -> odd a && odd b) (NonEmptyArray [1, 3, 2, 4, 3, 3]) +-- | = NonEmptyArray [NonEmptyArray [1, 3], NonEmptyArray [2], NonEmptyArray [4], NonEmptyArray [3, 3]] +-- | ``` +-- | groupBy :: forall a. (a -> a -> Boolean) -> NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) groupBy op = unsafeAdapt $ A.groupBy op +-- | Group equal elements of an array into arrays, using the specified +-- | comparison function to determine equality. +-- | +-- | ```purescript +-- | groupAllBy (comparing Down) (NonEmptyArray [1, 3, 2, 4, 3, 3]) +-- | = NonEmptyArray [NonEmptyArray [4], NonEmptyArray [3, 3, 3], NonEmptyArray [2], NonEmptyArray [1]] +-- | ``` +groupAllBy :: forall a. (a -> a -> Ordering) -> NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +groupAllBy op = unsafeAdapt $ A.groupAllBy op + nub :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray a nub = unsafeAdapt A.nub diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index 02295089..a778bec3 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -9,6 +9,7 @@ import Data.Const (Const(..)) import Data.Foldable (for_, foldMapDefaultR, class Foldable, all, traverse_) import Data.Traversable (scanl, scanr) import Data.Maybe (Maybe(..), isNothing, fromJust) +import Data.Ord.Down (Down(..)) import Data.Tuple (Tuple(..)) import Data.Unfoldable (replicateA) import Effect (Effect) @@ -362,11 +363,11 @@ testArray = do log "groupBy should be stable" assert $ A.groupBy (\_ _ -> true) [1, 2, 3] == [nea [1, 2, 3]] - log "groupAllBy should group equal elements into arrays based on an equivalence relation" - assert $ A.groupAllBy (\x y -> odd x && odd y) [1, 3, 2, 4, 3, 3] == [nea [1], nea [2], nea [3, 3, 3], nea [4]] + log "groupAllBy should group equal elements into arrays based on the result of a comparison function" + assert $ A.groupAllBy (comparing Down) [1, 3, 2, 4, 3, 3] == [nea [4], nea [3, 3, 3], nea [2], nea [1]] log "groupAllBy should be stable" - assert $ A.groupAllBy (\_ _ -> true) [1, 2, 3] == [nea [1, 2, 3]] + assert $ A.groupAllBy (\_ _ -> EQ) [1, 2, 3] == [nea [1, 2, 3]] log "nub should remove duplicate elements from the list, keeping the first occurence" assert $ A.nub [1, 2, 2, 3, 4, 1] == [1, 2, 3, 4] diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index a9ffead2..cb183df1 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -10,6 +10,7 @@ import Data.FunctorWithIndex (mapWithIndex) import Data.Maybe (Maybe(..), fromJust) import Data.Monoid.Additive (Additive(..)) import Data.NonEmpty ((:|)) +import Data.Ord.Down (Down(..)) import Data.Semigroup.Foldable (foldMap1, foldr1, foldl1) import Data.Semigroup.Traversable (traverse1) import Data.Tuple (Tuple(..)) @@ -25,6 +26,9 @@ testNonEmptyArray = do let fromArray :: forall a. Array a -> NEA.NonEmptyArray a fromArray = unsafePartial fromJust <<< NEA.fromArray + nea :: forall a. Array a -> NEA.NonEmptyArray a + nea = fromArray + log "singleton should construct an array with a single value" assert $ NEA.toArray (NEA.singleton 1) == [1] assert $ NEA.toArray (NEA.singleton "foo") == ["foo"] @@ -247,8 +251,8 @@ testNonEmptyArray = do log "group should group consecutive equal elements into arrays" assert $ NEA.group (fromArray [1, 2, 2, 3, 3, 3, 1]) == fromArray [NEA.singleton 1, fromArray [2, 2], fromArray [3, 3, 3], NEA.singleton 1] - log "group' should sort then group consecutive equal elements into arrays" - assert $ NEA.group' (fromArray [1, 2, 2, 3, 3, 3, 1]) == fromArray [fromArray [1, 1], fromArray [2, 2], fromArray [3, 3, 3]] + log "groupAll should group equal elements into arrays" + assert $ NEA.groupAll (fromArray [1, 2, 2, 3, 3, 3, 1]) == fromArray [fromArray [1, 1], fromArray [2, 2], fromArray [3, 3, 3]] log "groupBy should group consecutive equal elements into arrays based on an equivalence relation" assert $ NEA.groupBy (\x y -> odd x && odd y) (fromArray [1, 1, 2, 2, 3, 3]) == fromArray [fromArray [1, 1], NEA.singleton 2, NEA.singleton 2, fromArray [3, 3]] @@ -256,6 +260,12 @@ testNonEmptyArray = do log "groupBy should be stable" assert $ NEA.groupBy (\_ _ -> true) (fromArray [1, 2, 3]) == fromArray [fromArray [1, 2, 3]] + log "groupAllBy should group equal elements into arrays based on the result of a comparison function" + assert $ NEA.groupAllBy (comparing Down) (fromArray [1, 3, 2, 4, 3, 3]) == fromArray [nea [4], nea [3, 3, 3], nea [2], nea [1]] + + log "groupAllBy should be stable" + assert $ NEA.groupAllBy (\_ _ -> EQ) (fromArray [1, 2, 3]) == fromArray [nea [1, 2, 3]] + log "nub should remove duplicate elements from the list, keeping the first occurence" assert $ NEA.nub (fromArray [1, 2, 2, 3, 4, 1]) == fromArray [1, 2, 3, 4]