我们可以使用seq<float>
从seq<float * float>
转到Seq.pairwise
。
但是如果给出一系列同质元组,我该如何回到序列?
我考虑了
someSeq |> Seq.map (fun a b -> seq { yield a; yield b })
但这给了我签名
seq<float * float> -> seq<(float * float -> seq<float * float>)>
我觉得我错过了什么......
答案 0 :(得分:5)
尝试使用Seq.collect
并将元组作为参数:
someSeq |> Seq.collect (fun (a, b) -> seq { yield a; yield b })
或 Daniel 注意:
someSeq |> Seq.collect (fun (a, b) -> [a; b])
但请注意,这与'un-pairwise'不完全相同,因为Seq.pairwise
将为原始列表中的每个相邻元素对生成一个元素。注意:
let a = [1..5]
let b = a |> Seq.pairwise
let c = b |> Seq.collect (fun (a, b) -> [a; b])
// c = [1; 2; 2; 3; 3; 4; 4; 5]
要真正“成对”成对序列,您可以执行以下操作(接受并返回seq
):
let unpairwise (x) =
seq {
if not(Seq.isEmpty x) then
let (a, b) = Seq.head x
yield a
yield b
yield! Seq.skip 1 x |> Seq.map (fun (a, b) -> b)
}
或者像这样(接受seq
,但返回list
):
let unpairwise (x) =
if Seq.isEmpty x then
[]
else
let (a, b) = Seq.head x
[ a; b ] @ [ for (a, b) in Seq.skip 1 x -> b ]
或者甚至可能是这样(接受并返回list
):
let unpairwise (x) =
match x with
| (a,b)::t -> [ a; b ] @ [ for (a, b) in t -> b ]
| _ -> []
答案 1 :(得分:4)
在这种情况下,序列表达式会更加惯用。
seq { for x, y in someSeq do yield x; yield y }
您的函数采用两个参数而不是一个元组。只有一个参数传递给这个lambda函数,但由于它需要两个,它返回一个带有缺失参数的新函数。
someSeq |> Seq.map(fun (a, b) -> seq { yield a; yield b })
这会给<seq<seq<float>>
。您可以使用seq<float>
转到Seq.concat
。
someSeq |> Seq.map(fun (a, b) -> seq { yield a; yield b }) |> Seq.concat
还Seq.collect
合并了Seq.map
和Seq.concat
。
someSeq |> Seq.collect(fun (a, b) -> seq { yield a; yield b })
这里是关于将部分参数传递给函数的MSDN F#文档的剪辑。
Partial Application of Arguments
如果提供的参数少于指定数量,则创建 一个期望剩余参数的新函数。这种方法 处理参数被称为currying并且是一个特征 像F#这样的函数式编程语言。
答案 2 :(得分:1)
我认为您可能打算将a b
作为(a, b)
的元组?否则,a
是元组,您将部分应用;映射到期望另一个元组的函数序列(因此float * float -> seq<float * float>
签名)。非常混乱!
然后,您可能希望使用Seq.concat
展平序列序列,或者使用Seq.collect
而不是map
来开始。
这样做你想要的吗?这仍然不是Seq.pairwise
的倒数。不确定这是不是你想要的......
答案 3 :(得分:1)
如果您需要将成对结构转换为原始列表,为什么不只是
let pw = Seq.pairwise { 1 .. 5 } //seq [(1, 2); (2, 3); (3, 4); (4, 5)]
let up = unpairwise pw |> Seq.toList //[ 1; 2; 3; 4; 5 ]
示例:
{{1}}