首页 > 解决方案 > 翻转二维列表(或列表列表)的维度,其中每个子列表的长度相同

问题描述

我有一个列表列表,其中每个内部列表具有相同的长度,我需要将其投影为它的倒数(也就是说,我需要翻转维度)。

换句话说,取出每个子列表的第一项并将其放入新列表,取出每个子列表的第二项并将其放入新列表等。然后返回所有这些新列表的列表。

示例:如果输入是:

let ls = [[1;2;3];[4;5;6];[7;8;9];[0;0;0]];;

那么输出应该是:

val it : int list list = [[1; 4; 7; 0]; [2; 5; 8; 0]; [3; 6; 9; 0]]

我有工作代码,但感觉不对。它遍历列表多次,需要执行List.rev多次并且必须检查内部列表是否为空:

let rec getInnerHeads acc skipped lst =
    match lst with
    | [] -> List.rev acc, List.rev skipped
    | item::rest ->
        match item with
        | [] -> [], skipped
        | innerHead::skip1 ->
            getInnerHeads (innerHead::acc) (skip1::skipped) rest

let rec flipDimensions acc lst =
    match lst with
    | [] -> acc |> List.rev
    | z when (z |> List.forall List.isEmpty) -> acc |> List.rev
    | rest ->
        let (elem, skip1Elems) = getInnerHeads [] [] rest
        flipDimensions (elem::acc) skip1Elems

上述代码的唯一优点是它是轨道递归的(至少我认为是这样)。

有人有更有效,更简洁,或两者兼而有之的算法吗?我检查了 F# Snippets 和 SO,认为这以前会被问过,这似乎很常见,但我没有找到任何示例。

也许有什么List.unfold

标签: algorithmlistrecursionf#

解决方案


let transpose matrix =
    let rec loop acc = function
        | (_::_)::_ as m -> loop (List.map List.head m :: acc) (List.map List.tail m)
        | _ -> List.rev acc
    loop [] matrix

推荐阅读