首页 > 解决方案 > 在 F# 中合并 2 个列表

问题描述

我有 2 个带有坐标的列表(每个轴一个),我正在用它们制作正方形:

// create all combinations
let squares = List<int * int * int * int>()
seqX
|> Seq.pairwise
|> Seq.iter (fun (x1, x2) ->
    seqY
    |> Seq.pairwise
    |> Seq.iter (fun (y1, y2) -> squares.Add(x1, y1, x2, y2))
)

有没有办法,使用收集功能来做到这一点?我不能使用 Seq.map 因为输出与迭代总数不匹配

|> Seq.map (fun (y1, y2) -> (x1, y1, x2, y2))

不管用

标签: f#

解决方案


您可以使用Seq.collect平面映射内部序列。

Collect(又名SelectManyLINQ 和flatMapJS)将每个项目投影到一个新序列上,并将结果展平。

   seqX 
   |> Seq.pairwise 
   |> Seq.collect(fun (x1, x2) -> seqY |> Seq.map(fun (y1, y2) -> (x1, x2, y1, y2))

或者您可以制作一个序列表达式来为您执行此操作,这对上述内容有所帮助:

 seq {
    for (x1, x2) in seqX |> Seq.pairwise do
    for (y1, y2) in seqY |> Seq.pairwise do
    yield (x1, x2, y1, y2) 
 }

当涉及深度时,序列表达式非常有用。这比为每个级别()编写嵌套闭包要干净得多seq |> Seq.collect (fun _ -> Seq.collect(fun...

这是一个示例,通过遍历所有可能的三角形并检查毕达哥拉斯定理,找到所有边小于 10 的直角三角形。

 seq {
    let sides = [1..10]   
    for a in sides do
    for b in sides do
    for c in sides do
    if a * a + b * b = c * c then
        yield (a, b, c) 
 }

这将是更丑陋的脱糖。


推荐阅读