'Is there a simple way to transform [[a;b;c];[d;e;f]] into [[a;d];[b;e];[c;f]] in OCaml? [duplicate]
I'd like to write a function in OCaml, using only recursivity that can transform any list of list that look like: [[a1;...;an];[b1;...bn];...;[z1;...;zn]] into [[a1;b1;...;z1];...;[an;...;zn]] what I've done so far is quite complex, I insert element by element reconstructing a new list every time ... and I'm sure there is a simpler way ...
My code so far:
let inserer l e i =
let rec aux l e i j =
match l with
| [] -> failwith "erreur position inexistante"
| t::q when j = i ->
if List.length t = 0 then
[e]::q
else
let t1 = List.hd t in
let q1 = List.tl t in
let l1 = t1::e::q1 in
l1::q
| t::q -> t::(aux q e i (j+1))
in
aux l e i 0
let inserer_liste b m =
let rec aux b m i =
match b with
| [] -> m
| t::q ->
let tmp = inserer m t i in
aux q tmp (i+1)
in
aux b m 0
let transform u n =
let rec aux u m =
match u with
| []-> m
| b::q ->
let tmp = inserer_liste b m in
aux q tmp
in
aux u (List.init n (fun _ -> []))
let u = [[1;2;3]; [4;5;6]; [7;8;9]]
let l = transform u 3
Solution 1:[1]
I have a feeling that this transformation is way more natural if you transform an array of lists into a lists of arrays. You can transform into a list of lists afterwards.
let rec f a =
match a.(0) with
| [] -> []
| _ :: _ ->
let hd = Array.map List.hd a in
for i = 0 to Array.length a - 1 do
a.(i) <- List.tl a.(i)
done ;
hd :: (f a)
This consumes the input array, which can be solved by shadowing f in the following way :
let f a = f (Array.copy a)
let f_list l = List.map Array.to_list (f (Array.of_list l))
You could also reallocate a new array at each recursive call, but that would be slower, without any upside except maybe a bit nicer code.
f_list is more elegant this way :
let f_list l =
l |> Array.of_list |> f |> List.map Array.to_list
There is no error handling in my code : it assumes all list have the same length, but it should be to hard to add it.
Solution 2:[2]
Is there a simple way... Not that I know of but that doesn't say much.
Here's something I tried.
let lol =
[
[ 1; 2; 3; 4; ];
[ 5; 6; 7; 8; ];
[ 9; 10; 11; 12; ];
]
let ans =
List.fold_left
(
fun a e ->
match a with
| [] -> List.fold_right (fun e a -> [e]::a) e a
| _ -> List.fold_right2 (fun b c acc -> (c @ [b])::acc) e a []
)
[]
lol
let () =
List.iter
(
fun l ->
List.iter (fun x -> Printf.printf "%d " x) l;
print_newline()
)
ans
After some thought I cam up with this
let lol =
[
[11; 12; 13; 14; 15; 16; 17; 18; 19; ];
[21; 22; 23; 24; 25; 26; 27; 28; 29; ];
[31; 32; 33; 34; 35; 36; 37; 38; 39; ];
[41; 42; 43; 44; 45; 46; 47; 48; 49; ];
]
let rec transpose ll =
match ll with
| [] -> []
| l -> (List.map List.hd l)::
(
try
transpose (List.map List.tl l)
with
| _ -> []
)
let ans = transpose lol
let () =
List.iter
(
fun l -> List.iter (fun x -> Printf.printf "%d " x) l; print_newline()
)
ans
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Emile Trotignon |
| Solution 2 |
