Skip to content

Commit 8e4d563

Browse files
committed
Use iterators to implement groupBy
Refs #71, improves performance of groupBy.
1 parent 5c74d19 commit 8e4d563

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

src/Data/Array.purs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,13 @@ module Data.Array
111111
) where
112112

113113
import Prelude
114-
115114
import Control.Alt ((<|>))
116115
import Control.Alternative (class Alternative)
117116
import Control.Lazy (class Lazy, defer)
118117
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
119-
118+
import Control.Monad.ST (pureST)
119+
import Data.Array.ST (unsafeFreeze, emptySTArray, pushSTArray)
120+
import Data.Array.ST.Iterator (iterator, iterate, pushWhile)
120121
import Data.Foldable (class Foldable, foldl, foldr)
121122
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
122123
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
@@ -125,7 +126,6 @@ import Data.Traversable (scanl, scanr) as Exports
125126
import Data.Traversable (sequence, traverse)
126127
import Data.Tuple (Tuple(..))
127128
import Data.Unfoldable (class Unfoldable, unfoldr)
128-
129129
import Partial.Unsafe (unsafePartial)
130130

131131
-- | Convert an `Array` into an `Unfoldable` structure.
@@ -548,14 +548,16 @@ group' = group <<< sort
548548
-- | Group equal, consecutive elements of an array into arrays, using the
549549
-- | specified equivalence relation to detemine equality.
550550
groupBy :: forall a. (a -> a -> Boolean) -> Array a -> Array (NonEmpty Array a)
551-
groupBy op = go []
552-
where
553-
go :: Array (NonEmpty Array a) -> Array a -> Array (NonEmpty Array a)
554-
go acc xs = case uncons xs of
555-
Just o ->
556-
let sp = span (op o.head) o.tail
557-
in go ((o.head :| sp.init) : acc) sp.rest
558-
Nothing -> reverse acc
551+
groupBy op xs =
552+
pureST do
553+
result <- emptySTArray
554+
iter <- iterator (xs !! _)
555+
iterate iter \x -> void do
556+
sub <- emptySTArray
557+
pushWhile (op x) iter sub
558+
sub_ <- unsafeFreeze sub
559+
pushSTArray result (x :| sub_)
560+
unsafeFreeze result
559561

560562
-- | Remove the duplicates from an array, creating a new array.
561563
nub :: forall a. Eq a => Array a -> Array a

0 commit comments

Comments
 (0)