Skip to content

Commit 9cfb41b

Browse files
committed
use Ord for nub
addresses purescript#91 O(n*logn)
1 parent 32a1a20 commit 9cfb41b

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/Data/Array.purs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,18 @@ import Prelude
117117
import Control.Alt ((<|>))
118118
import Control.Alternative (class Alternative)
119119
import Control.Lazy (class Lazy, defer)
120+
import Control.Monad.Eff (foreachE)
120121
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
121122
import Control.Monad.ST (pureST)
122-
import Data.Array.ST (unsafeFreeze, emptySTArray, pokeSTArray, pushSTArray, modifySTArray, withArray)
123+
import Data.Array.ST (unsafeFreeze, unsafeThaw, emptySTArray, pokeSTArray, pushSTArray, modifySTArray, withArray)
123124
import Data.Array.ST.Iterator (iterator, iterate, pushWhile)
124125
import Data.Foldable (class Foldable, foldl, foldr, traverse_)
125126
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
126127
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
127128
import Data.NonEmpty (NonEmpty, (:|))
128129
import Data.Traversable (scanl, scanr) as Exports
129130
import Data.Traversable (sequence, traverse)
130-
import Data.Tuple (Tuple(..), uncurry)
131+
import Data.Tuple (Tuple(..), fst, snd, uncurry)
131132
import Data.Unfoldable (class Unfoldable, unfoldr)
132133
import Partial.Unsafe (unsafePartial)
133134

@@ -873,8 +874,19 @@ groupBy op xs =
873874
-- | nub [1, 2, 1, 3, 3] = [1, 2, 3]
874875
-- | ```
875876
-- |
876-
nub :: forall a. Eq a => Array a -> Array a
877-
nub = nubBy eq
877+
nub :: forall a. Ord a => Array a -> Array a
878+
nub arr = case head indexedAndSorted of
879+
Nothing -> []
880+
Just x -> map fst $ sortWith snd $ pureST do
881+
-- TODO: use NonEmptyArrays here to avoid partial functions
882+
result <- unsafeThaw $ singleton x
883+
foreachE indexedAndSorted \pair@(Tuple x' i) -> do
884+
lst <- fst <<< unsafePartial (fromJust <<< last) <$> unsafeFreeze result
885+
when (lst /= x') $ void $ pushSTArray result pair
886+
unsafeFreeze result
887+
888+
where
889+
indexedAndSorted = sort $ mapWithIndex (flip Tuple) arr
878890

879891
-- | Remove the duplicates from an array, where element equality is determined
880892
-- | by the specified equivalence relation, creating a new array.

test/Test/Data/Array.purs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ testArray = do
313313
log "nub should remove duplicate elements from the list, keeping the first occurence"
314314
assert $ A.nub [1, 2, 2, 3, 4, 1] == [1, 2, 3, 4]
315315

316+
log "nub should preserve order"
317+
assert $ A.nub [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
318+
316319
log "nubBy should remove duplicate items from the list using a supplied predicate"
317320
let nubPred = \x y -> if odd x then false else x == y
318321
assert $ A.nubBy nubPred [1, 2, 2, 3, 3, 4, 4, 1] == [1, 2, 3, 3, 4, 1]

0 commit comments

Comments
 (0)