使用以下数据(随机字符串):
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]
通过取每列
的最大值我想我可以做一个折叠,并以第一行为起点,但它看起来会很复杂。
For context:这是一个函数,它将获取一个网格并以适当的间距/格式显示它;所有行必须具有相同数量的元素。
您需要list .转置。这将行转换为列,反之亦然。
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)
相同,但我们不需要使用h
和t
,因此将不关心的占位符_
代替。
第二个::
确保列表列表(listoflists)不为空,或者(h::t)::c
= (head of listoflists)::tail of listoflists,因此h::t
是第一行,c
是所有其他行。
(_::_)::_ <=> (headRow0::tailRow0)::tailRows