我们假设我有一系列的序列,例如,F#
{1, 2, 3}, {1, 2, 3}, {1, 2, 3}
什么是转动或压缩这个序列,所以我反而有最好的方式,
{1, 1, 1}, {2, 2, 2}, {3, 3, 3}
有没有这样做,而不诉诸底层IEnumerator<_>
类型的操纵的理解呢?
要澄清,这些是seq<seq<int>>
对象。每个序列(内部和外部)可以有任意数量的项目。
我们假设我有一系列的序列,例如,F#
{1, 2, 3}, {1, 2, 3}, {1, 2, 3}
什么是转动或压缩这个序列,所以我反而有最好的方式,
{1, 1, 1}, {2, 2, 2}, {3, 3, 3}
有没有这样做,而不诉诸底层IEnumerator<_>
类型的操纵的理解呢?
要澄清,这些是seq<seq<int>>
对象。每个序列(内部和外部)可以有任意数量的项目。
如果您要寻找Seq语义解决方案,您将不得不一直保持懒惰。
let zip seq = seq
|> Seq.collect(fun s -> s |> Seq.mapi(fun i e -> (i, e))) //wrap with index
|> Seq.groupBy(fst) //group by index
|> Seq.map(fun (i, s) -> s |> Seq.map snd) //unwrap
测试:
let seq = Enumerable.Repeat((seq [1; 2; 3]), 3) //don't want to while(true) yield. bleh.
printfn "%A" (zip seq)
输出:
seq [seq [1; 1; 1]; seq [2; 2; 2]; seq [3; 3; 3]]
虽然这将工作,但Seq.groupBy不是懒惰的,并且一旦从Seq.groupBy请求第一个元素,就会完全评估它的输入序列 –
这似乎非常不雅,但它得到正确的答案:
(seq [(1, 2, 3); (1, 2, 3); (1, 2, 3);])
|> Seq.fold (fun (sa,sb,sc) (a,b,c) ->a::sa,b::sb,c::sc) ([],[],[])
|> fun (a,b,c) -> a::b::c::[]
它看起来很有前途,但是如何将seq
OP的问题需要解决方案对可变长度的序列进行操作,而不是一系列n元组。 – Asti
它看起来像矩阵转置。
let data =
seq [
seq [1; 2; 3]
seq [1; 2; 3]
seq [1; 2; 3]
]
let rec transpose = function
| (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
// I don't claim it is very elegant, but no doubt it is readable
let result =
data
|> List.ofSeq
|> List.map List.ofSeq
|> transpose
|> Seq.ofList
|> Seq.map Seq.ofList
或者,您可以采用相同的方法seq
,感谢this answer一个优雅的活动模式:
let (|SeqEmpty|SeqCons|) (xs: 'a seq) =
if Seq.isEmpty xs then SeqEmpty
else SeqCons(Seq.head xs, Seq.skip 1 xs)
let rec transposeSeq = function
| SeqCons(SeqCons(_,_),_) as M ->
Seq.append
(Seq.singleton (Seq.map Seq.head M))
(transposeSeq (Seq.map (Seq.skip 1) M))
| _ -> Seq.empty
let resultSeq = data |> transposeSeq
又见this answer的技术细节和两个引用:到的PowerPack的Microsoft.FSharp.Math.Matrix
和涉及可变数据的另一种方法。
尽管如此,它仍然对所有的序列进行了评估。 'Seq.ofList'什么都不做,只是将列表强制转换为'seq <'t>',所以将签名作为'seq
这是相同的答案@Asti,只是清理了一点:
[[1;2;3]; [1;2;3]; [1;2;3]]
|> Seq.collect Seq.indexed
|> Seq.groupBy fst
|> Seq.map (snd >> Seq.map snd);;
所以你要做一个矩阵转置或一个元素组合 - 这不是很好明确。一个更长的输入的例子是好的。 –
[我如何在F#中编写类似ZipN的函数?]的可能重复(http://stackoverflow.com/questions/11770441/how-do-i-write-a-zipn-like-function-in-f ) – Daniel