Skip to content

Commit 3f0201f

Browse files
matthewleonkritzcreek
authored andcommitted
use Ord for nub
addresses #91 O(n*logn)
1 parent a3e568e commit 3f0201f

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/Data/Array.purs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ import Prelude
118118
import Control.Alt ((<|>))
119119
import Control.Alternative (class Alternative)
120120
import Control.Lazy (class Lazy, defer)
121+
import Control.Monad.Eff (foreachE)
121122
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
122123
import Control.Monad.ST as ST
123124
import Data.Array.ST as STA
@@ -128,7 +129,7 @@ import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, f
128129
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
129130
import Data.Traversable (scanl, scanr) as Exports
130131
import Data.Traversable (sequence, traverse)
131-
import Data.Tuple (Tuple(..))
132+
import Data.Tuple (Tuple(..), fst, snd, uncurry)
132133
import Data.Unfoldable (class Unfoldable, unfoldr)
133134
import Partial.Unsafe (unsafePartial)
134135
import Unsafe.Coerce (unsafeCoerce)
@@ -876,8 +877,19 @@ groupBy op xs =
876877
-- | nub [1, 2, 1, 3, 3] = [1, 2, 3]
877878
-- | ```
878879
-- |
879-
nub :: forall a. Eq a => Array a -> Array a
880-
nub = nubBy eq
880+
nub :: forall a. Ord a => Array a -> Array a
881+
nub arr = case head indexedAndSorted of
882+
Nothing -> []
883+
Just x -> map fst $ sortWith snd $ pureST do
884+
-- TODO: use NonEmptyArrays here to avoid partial functions
885+
result <- unsafeThaw $ singleton x
886+
foreachE indexedAndSorted \pair@(Tuple x' i) -> do
887+
lst <- fst <<< unsafePartial (fromJust <<< last) <$> unsafeFreeze result
888+
when (lst /= x') $ void $ pushSTArray result pair
889+
unsafeFreeze result
890+
891+
where
892+
indexedAndSorted = sort $ mapWithIndex (flip Tuple) arr
881893

882894
-- | Remove the duplicates from an array, where element equality is determined
883895
-- | 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
@@ -309,6 +309,9 @@ testArray = do
309309
log "nub should remove duplicate elements from the list, keeping the first occurence"
310310
assert $ A.nub [1, 2, 2, 3, 4, 1] == [1, 2, 3, 4]
311311

312+
log "nub should preserve order"
313+
assert $ A.nub [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2]
314+
312315
log "nubBy should remove duplicate items from the list using a supplied predicate"
313316
let nubPred = \x y -> if odd x then false else x == y
314317
assert $ A.nubBy nubPred [1, 2, 2, 3, 3, 4, 4, 1] == [1, 2, 3, 3, 4, 1]

0 commit comments

Comments
 (0)