[英]Pivot or zip a seq<seq<'a>> in F#
Let's say I have a sequence of sequences, eg 假设我有一个序列序列,例如
{1, 2, 3}, {1, 2, 3}, {1, 2, 3}
What is the best way to pivot or zip this sequence so I instead have, 枢转或压缩此序列的最佳方法是什么,所以我有了
{1, 1, 1}, {2, 2, 2}, {3, 3, 3}
Is there a comprehensible way of doing so without resorting to manipulation of the underlying IEnumerator<_>
type? 是否有一种可理解的方式来实现,而无需借助对基础
IEnumerator<_>
类型的操纵?
To clarify, these are seq<seq<int>>
objects. 为了澄清起见,这些是
seq<seq<int>>
对象。 Each sequences (both internal and external) can have any number of items. 每个序列(内部和外部)都可以具有任意数量的项目。
If you're going for a solution which is semantically Seq, you're going to have to stay lazy all the time. 如果您要使用语义上为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
Test: 测试:
let seq = Enumerable.Repeat((seq [1; 2; 3]), 3) //don't want to while(true) yield. bleh.
printfn "%A" (zip seq)
Output: 输出:
seq [seq [1; 1; 1]; seq [2; 2; 2]; seq [3; 3; 3]]
This seems very inelegant but it gets the right answer: 这似乎很不雅致,但它得到了正确的答案:
(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::[]
It looks like matrix transposition. 它看起来像矩阵转置。
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
Alternatively, you may adopt the same method for seq
, thanks to this answer for an elegant Active pattern: 另外,您可以对
seq
采用相同的方法,这要归功于优雅的Active模式的答案 :
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
See also this answer for technical details and two references: to PowerPack 's Microsoft.FSharp.Math.Matrix
and yet another method involving mutable data . 另请参阅此答案以获取技术细节和两个参考: PowerPack的
Microsoft.FSharp.Math.Matrix
和涉及可变数据的另一种方法。
This is the same answer as @Asti, just cleaned up a little: 这和@Asti的答案是一样的,只是清理了一下:
[[1;2;3]; [1;2;3]; [1;2;3]]
|> Seq.collect Seq.indexed
|> Seq.groupBy fst
|> Seq.map (snd >> Seq.map snd);;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.