Skip to content

Commit e5d80f3

Browse files
Add transpose to Data.Array (#226)
* Add transpose to Data.Array Implementation courtesy of Jordan Martinez. * Update CHANGELOG * Improve layout of doc comments
1 parent d20bae2 commit e5d80f3

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Notable changes to this project are documented in this file. The format is based
77
Breaking changes:
88

99
New features:
10+
- Added `transpose` to `Array` (#225 by @newlandsvalley and @JordanMartinez)
1011

1112
Bugfixes:
1213

src/Data/Array.purs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ module Data.Array
8484
, foldMap
8585
, fold
8686
, intercalate
87+
, transpose
8788
, scanl
8889
, scanr
8990

@@ -781,6 +782,46 @@ fold = F.fold
781782
intercalate :: forall a. Monoid a => a -> Array a -> a
782783
intercalate = F.intercalate
783784

785+
-- | The 'transpose' function transposes the rows and columns of its argument.
786+
-- | For example,
787+
-- |
788+
-- | ```purescript
789+
-- | transpose
790+
-- | [ [1, 2, 3]
791+
-- | , [4, 5, 6]
792+
-- | ] ==
793+
-- | [ [1, 4]
794+
-- | , [2, 5]
795+
-- | , [3, 6]
796+
-- | ]
797+
-- | ```
798+
-- |
799+
-- | If some of the rows are shorter than the following rows, their elements are skipped:
800+
-- |
801+
-- | ```purescript
802+
-- | transpose
803+
-- | [ [10, 11]
804+
-- | , [20]
805+
-- | , [30, 31, 32]
806+
-- | ] ==
807+
-- | [ [10, 20, 30]
808+
-- | , [11, 31]
809+
-- | , [32]
810+
-- | ]
811+
-- | ```
812+
transpose :: forall a. Array (Array a) -> Array (Array a)
813+
transpose xs = go 0 []
814+
where
815+
go :: Int -> Array (Array a) -> Array (Array a)
816+
go idx allArrays = case buildNext idx of
817+
Nothing -> allArrays
818+
Just next -> go (idx + 1) (snoc allArrays next)
819+
820+
buildNext :: Int -> Maybe (Array a)
821+
buildNext idx = do
822+
xs # flip foldl Nothing \acc nextArr -> do
823+
maybe acc (\el -> Just $ maybe [el] (flip snoc el) acc) $ index nextArr idx
824+
784825
-- | Fold a data structure from the left, keeping all intermediate results
785826
-- | instead of only the final result. Note that the initial value does not
786827
-- | appear in the result (unlike Haskell's `Prelude.scanl`).

test/Test/Data/Array.purs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,20 @@ testArray = do
265265
assert $ A.modifyAtIndices [0, 2, 8] not [true, true, true, true] ==
266266
[false, true, false, true]
267267

268+
log "transpose swaps rows and columns for a regular two-dimension array"
269+
assert $ A.transpose [[1,2,3], [4,5,6], [7,8,9]] ==
270+
[[1,4,7], [2,5,8], [3,6,9]]
271+
272+
log "transpose skips elements when rows don't match"
273+
assert $ A.transpose [[10,11], [20], [30,31,32]] ==
274+
[[10,20,30], [11,31], [32]]
275+
276+
log "transpose [] == []"
277+
assert $ A.transpose [] == ([] :: Array (Array Int))
278+
279+
log "transpose (singleton []) == []"
280+
assert $ A.transpose (A.singleton []) == ([] :: Array (Array Int))
281+
268282
log "scanl should return an array that stores the accumulated value at each step"
269283
assert $ A.scanl (+) 0 [1,2,3] == [1, 3, 6]
270284
assert $ A.scanl (-) 10 [1,2,3] == [9, 7, 4]

0 commit comments

Comments
 (0)