【问题标题】:how to calculate the max by column in a list of lists, with F#如何使用 F# 在列表列表中按列计算最大值
【发布时间】:2021-02-18 19:35:05
【问题描述】:

使用以下数据(随机字符串):

let data =
    [
        ["shi"; "cjwocij"; "cjwijo"]
        ["abs"; "djw"; "djwjdwojdow"]
        ["djido"; "dkwpkw"; "dpfkpeoep"]
    ]

我想按列计算最大长度。 我可以将数据转换为长度列表:

data |> List.map (fun r -> r |> List.map (fun x -> x.Length))
index   value
0       [ 3; 7; 6 ]
1       [ 3; 3; 11 ]
2       [ 5; 6; 9 ]

但最终我想将其简化为:

[5; 7; 11]

取每一列的最大值

我以为我可以折叠并以第一行为起点,但看起来会很复杂。

对于上下文:这是一个函数,它将采用一个网格并以适当的间距/格式显示它;所有行必须具有相同数量的元素。

【问题讨论】:

    标签: f#


    【解决方案1】:

    你需要 List.transpose。这会将行转换为列,反之亦然。

    data 
    |> List.map (fun r -> r |> List.map (fun x -> x.Length)) 
    |> List.transpose
    |> List.map List.max
    
    val data : string list list =
      [["shi"; "cjwocij"; "cjwijo"]; ["abs"; "djw"; "djwjdwojdow"];
       ["djido"; "dkwpkw"; "dpfkpeoep"]]
    val it : int list = [5; 7; 11]
    

    这是一个快速的显式转置版本,它可能有助于(或阻碍?)你理解这一点:

    let transpose lists =
        [0 .. (List.length (List.head lists)) - 1]
        |> List.map (fun col -> List.map (fun row -> List.item col row) lists )
    

    为了完整起见,这是递归版本,但我认为如果您是 F# 新手,上述内容会更清楚。

    let rec transpose = function
        | (_::_)::_ as l -> List.map List.head l :: transpose (List.map List.tail l)
        | _ -> []
    

    更新:我在评论中回答了这个问题,但其他人想知道第二个递归解决方案:

    (_::_) 确保列表不为空。这与(h::t) 相同,但我们不需要使用ht,因此请使用无关占位符_

    第二个:: 确保列表列表(listoflists)不为空,或者(h::t)::c = (listoflists 的头部)::listoflists 的尾部,所以h::t 是第一行,@987654332 @ 是所有其他行。

    (_::_)::_ <=> (headRow0::tailRow0)::tailRows
    

    【讨论】:

    • 这很好用,谢谢!我理解第一个版本没有困难,但我对第二个版本有点挣扎:如果我理解,它会尝试将输入与模式匹配,但我没有得到 (::)::_ 模式,你能解释一下吗?
    • 感谢您的详细解释。我已经用一堆 printfs 对递归版本进行了检测,以便逐步查看它的工作。
    猜你喜欢
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 2023-04-07
    • 1970-01-01
    相关资源
    最近更新 更多