Skip to content

Commit

Permalink
Add transpose to Data.Array (#226)
Browse files Browse the repository at this point in the history
* Add transpose to Data.Array

Implementation courtesy of Jordan Martinez.

* Update CHANGELOG

* Improve layout of doc comments
  • Loading branch information
newlandsvalley authored Jul 28, 2022
1 parent d20bae2 commit e5d80f3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Notable changes to this project are documented in this file. The format is based
Breaking changes:

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

Bugfixes:

Expand Down
41 changes: 41 additions & 0 deletions src/Data/Array.purs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ module Data.Array
, foldMap
, fold
, intercalate
, transpose
, scanl
, scanr

Expand Down Expand Up @@ -781,6 +782,46 @@ fold = F.fold
intercalate :: forall a. Monoid a => a -> Array a -> a
intercalate = F.intercalate

-- | The 'transpose' function transposes the rows and columns of its argument.
-- | For example,
-- |
-- | ```purescript
-- | transpose
-- | [ [1, 2, 3]
-- | , [4, 5, 6]
-- | ] ==
-- | [ [1, 4]
-- | , [2, 5]
-- | , [3, 6]
-- | ]
-- | ```
-- |
-- | If some of the rows are shorter than the following rows, their elements are skipped:
-- |
-- | ```purescript
-- | transpose
-- | [ [10, 11]
-- | , [20]
-- | , [30, 31, 32]
-- | ] ==
-- | [ [10, 20, 30]
-- | , [11, 31]
-- | , [32]
-- | ]
-- | ```
transpose :: forall a. Array (Array a) -> Array (Array a)
transpose xs = go 0 []
where
go :: Int -> Array (Array a) -> Array (Array a)
go idx allArrays = case buildNext idx of
Nothing -> allArrays
Just next -> go (idx + 1) (snoc allArrays next)

buildNext :: Int -> Maybe (Array a)
buildNext idx = do
xs # flip foldl Nothing \acc nextArr -> do
maybe acc (\el -> Just $ maybe [el] (flip snoc el) acc) $ index nextArr idx

-- | Fold a data structure from the left, keeping all intermediate results
-- | instead of only the final result. Note that the initial value does not
-- | appear in the result (unlike Haskell's `Prelude.scanl`).
Expand Down
14 changes: 14 additions & 0 deletions test/Test/Data/Array.purs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,20 @@ testArray = do
assert $ A.modifyAtIndices [0, 2, 8] not [true, true, true, true] ==
[false, true, false, true]

log "transpose swaps rows and columns for a regular two-dimension array"
assert $ A.transpose [[1,2,3], [4,5,6], [7,8,9]] ==
[[1,4,7], [2,5,8], [3,6,9]]

log "transpose skips elements when rows don't match"
assert $ A.transpose [[10,11], [20], [30,31,32]] ==
[[10,20,30], [11,31], [32]]

log "transpose [] == []"
assert $ A.transpose [] == ([] :: Array (Array Int))

log "transpose (singleton []) == []"
assert $ A.transpose (A.singleton []) == ([] :: Array (Array Int))

log "scanl should return an array that stores the accumulated value at each step"
assert $ A.scanl (+) 0 [1,2,3] == [1, 3, 6]
assert $ A.scanl (-) 10 [1,2,3] == [9, 7, 4]
Expand Down

0 comments on commit e5d80f3

Please sign in to comment.