I'm trying to make a recursive function to get the transpose of a list of lists, n x p
to p x n
. But i'm unable to do so. I've been able to make a function to transpose a 3 x n
list of lists to an n x 3
one:
let rec drop1 list=
[(match (List.nth list 0) with [] -> [] | a::b -> b);
(match (List.nth list 1) with [] -> [] | a::b -> b);
(开发者_运维百科match (List.nth list 2) with [] -> [] | a::b -> b);]
let rec transpose list=
if List.length (List.nth list 0) == 0 then []
else [(match (List.nth list 0) with [] -> 0 | a::b -> a);
(match (List.nth list 1) with [] -> 0 | a::b -> a);
(match (List.nth list 2) with [] -> 0 | a::b -> a)]
:: transpose (drop1 list)
But I'm not able to generalize it. I'm surely thinking in the wrong direction. Is this generalizable? Is there a better solution? Please help.
let rec transpose list = match list with
| [] -> []
| [] :: xss -> transpose xss
| (x::xs) :: xss ->
(x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss)
Taking advantage of syntax changes since answer first posted:
let rec transpose list = match list with
| [] -> []
| [] :: xss -> transpose xss
| (x::xs) :: xss ->
List.(
(x :: map hd xss) :: transpose (xs :: map tl xss)
)
I know this is an old question, but I recently had to solve this as part of an exercise I was doing, and I came across @sepp2k's solution, but I couldn't understand how it worked, so I tried to arrive at it by myself.
This is essentially the same algorithm, but a little bit more terse, as it does not destructure the list of lists. I thought I would post it here in case anyone else is searching, and might find this way of expressing it useful:
let rec transpose = function
| []
| [] :: _ -> []
| rows ->
List.map List.hd rows :: transpose (List.map List.tl rows)
Assuming the matrix is rectangular (otherwise Invalid_argument "map2"
will be raised):
let transpose m =
if m = [] then [] else
List.(fold_right (map2 cons) m @@ map (fun _ -> []) (hd m))
Note that map (fun _ -> []) (hd m)
just creates a list of empty lists, of length equal to the number of columns in m
.
So a clearer representation of this code would be:
let transpose m =
if m = [] then [] else
let open List in
let empty_rows = map (fun _ -> []) (hd m) in
fold_right (map2 cons) m empty_rows
精彩评论