Skip to content

Commit 580ccce

Browse files
committed
STArray: in-place sort
1 parent 32a1a20 commit 580ccce

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

src/Data/Array/ST.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ exports.copyImpl = function (xs) {
5858
};
5959
};
6060

61+
exports.sortByImpl = function (comp) {
62+
return function (xs) {
63+
return function () {
64+
return xs.sort(function (x, y) {
65+
return comp(x)(y);
66+
});
67+
};
68+
};
69+
};
70+
6171
exports.toAssocArray = function (xs) {
6272
return function () {
6373
var n = xs.length;

src/Data/Array/ST.purs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ module Data.Array.ST
1414
, modifySTArray
1515
, pushAllSTArray
1616
, spliceSTArray
17+
, sort
18+
, sortBy
19+
, sortWith
1720
, freeze
1821
, thaw
1922
, unsafeFreeze
@@ -80,6 +83,38 @@ foreign import emptySTArray :: forall a h r. Eff (st :: ST h | r) (STArray h a)
8083
thaw :: forall a h r. Array a -> Eff (st :: ST h | r) (STArray h a)
8184
thaw = copyImpl
8285

86+
-- | Sort a mutable array in place.
87+
sort :: forall a h r. Ord a => STArray h a -> Eff (st :: ST h | r) (STArray h a)
88+
sort = sortBy compare
89+
90+
-- | Sort a mutable array in place using a comparison function.
91+
sortBy
92+
:: forall a h r
93+
. (a -> a -> Ordering)
94+
-> STArray h a
95+
-> Eff (st :: ST h | r) (STArray h a)
96+
sortBy comp = sortByImpl comp'
97+
where
98+
comp' x y = case comp x y of
99+
GT -> 1
100+
EQ -> 0
101+
LT -> -1
102+
103+
foreign import sortByImpl
104+
:: forall a h r
105+
. (a -> a -> Int)
106+
-> STArray h a
107+
-> Eff (st :: ST h | r) (STArray h a)
108+
109+
-- | Sort a mutable array in place based on a projection.
110+
sortWith
111+
:: forall a b h r
112+
. Ord b
113+
=> (a -> b)
114+
-> STArray h a
115+
-> Eff (st :: ST h | r) (STArray h a)
116+
sortWith f = sortBy (comparing f)
117+
83118
-- | Create an immutable copy of a mutable array.
84119
freeze :: forall a h r. STArray h a -> Eff (st :: ST h | r) (Array a)
85120
freeze = copyImpl

test/Test/Data/Array/ST.purs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Prelude
44
import Control.Monad.Eff (Eff)
55
import Control.Monad.Eff.Console (log, CONSOLE)
66
import Control.Monad.ST (ST, pureST)
7-
import Data.Array.ST (STArray, emptySTArray, freeze, peekSTArray, pokeSTArray, pushAllSTArray, pushSTArray, spliceSTArray, thaw, toAssocArray, unsafeThaw, unsafeFreeze)
7+
import Data.Array.ST (STArray, emptySTArray, freeze, peekSTArray, pokeSTArray, pushAllSTArray, pushSTArray, sort, sortBy, sortWith, spliceSTArray, thaw, toAssocArray, unsafeThaw, unsafeFreeze)
88
import Data.Foldable (all)
99
import Data.Maybe (Maybe(..), isNothing)
1010
import Test.Assert (assert, ASSERT)
@@ -132,6 +132,21 @@ testArrayST = do
132132
void $ pokeSTArray arr 1 2
133133
pure arr) == [1]
134134

135+
log "sort should reorder a list into ascending order based on the result of compare"
136+
assert $ run (
137+
sort =<< unsafeThaw [1, 3, 2, 5, 6, 4]
138+
) == [1, 2, 3, 4, 5, 6]
139+
140+
log "sortBy should reorder a list into ascending order based on the result of a comparison function"
141+
assert $ run (
142+
sortBy (flip compare) =<< unsafeThaw [1, 3, 2, 5, 6, 4]
143+
) == [6, 5, 4, 3, 2, 1]
144+
145+
log "sortWith should reorder a list into ascending order based on the result of compare over a projection"
146+
assert $ run (
147+
sortWith id =<< unsafeThaw [1, 3, 2, 5, 6, 4]
148+
) == [1, 2, 3, 4, 5, 6]
149+
135150
log "spliceSTArray should be able to delete multiple items at a specified index"
136151

137152
assert $ run (do

0 commit comments

Comments
 (0)