From ad9b08e43dd06260a52543f9078fc921c130cc9a Mon Sep 17 00:00:00 2001 From: sterni Date: Sat, 9 Mar 2024 13:17:30 +0100 Subject: feat(sterni/nix/lists): implement transpose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is inspired by BQN's [⍉] though it is much less elegant since Nix lacks multi-dimensional arrays. I thought this would be useful to to avoid multiple `map`s over a single list if we want to return multiple, separate values from it: transpose (builtins.map (x: [ (calcA x) (calcB x) ]) myList) # => [ [ (calcA a) … ] [ (calcB a) … ] ] While this is quite elegant, it turns out that it is faster to write out multiple maps: [ (builtins.map calcA myList) (builtins.map calcB myList) ] [⍉]: https://mlochbaum.github.io/BQN/doc/transpose.html Change-Id: Ic333c33af38ab03573b215c9696d75caf2ee18e7 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11113 Reviewed-by: sterni Autosubmit: sterni Tested-by: BuildkiteCI --- users/sterni/nix/list/default.nix | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 users/sterni/nix/list/default.nix (limited to 'users') diff --git a/users/sterni/nix/list/default.nix b/users/sterni/nix/list/default.nix new file mode 100644 index 0000000000..568a76d637 --- /dev/null +++ b/users/sterni/nix/list/default.nix @@ -0,0 +1,30 @@ +{ ... }: + +{ + /* For a list of length n that consists of lists of length m, + return a list of length m containing lists of length n + so that + + builtins.elemAt (builtins.elemAt orig a) b + == builtins.elemAt (builtins.elemAt transposed b) a + + Essentially, if you think of the nested list as an array with two + dimensions, the two index axes are swapped. + + The length of the inner lists m is determined based on the first element + and assumed to be used for all other lists. Malformed input data may + cause the function to crash or lose data. + + Type: [ [ ] ] -> [ [ ] ] + */ + transpose = list: + let + innerLength = builtins.length (builtins.head list); + outerLength = builtins.length list; + in + builtins.genList + (inner: builtins.genList + (outer: builtins.elemAt (builtins.elemAt list outer) inner) + outerLength) + innerLength; +} -- cgit 1.4.1