2012-10-07 32 views
5

Giả sử tôi có một chuỗi các chuỗi, ví dụ:Xoay vòng hoặc zip a seq <seq<'a>> trong F #

{1, 2, 3}, {1, 2, 3}, {1, 2, 3} 

cách tốt nhất để xoay hoặc zip chuỗi này vì vậy tôi thay vì phải có một cách hiểu làm như vậy mà không cần đến thao tác của các lớp dưới IEnumerator<_> loại là gì,

{1, 1, 1}, {2, 2, 2}, {3, 3, 3} 

là?

Để làm rõ, đây là các đối tượng seq<seq<int>>. Mỗi chuỗi (cả nội bộ và bên ngoài) có thể có bất kỳ số lượng mục nào.

+0

Vì vậy, bạn có muốn để làm một chuyển vị ma trận hoặc nhóm bởi một phần tử - đây không phải là rất thông thoáng. Một ví dụ cho một đầu vào dài hơn sẽ là tốt. –

+1

có thể trùng lặp của [Làm thế nào để viết một hàm giống như ZipN trong F #?] (Http://stackoverflow.com/questions/11770441/how-do-i-write-a-zipn-like-function-in-f) – Daniel

Trả lời

3

Nếu bạn đang đi cho một giải pháp đó là ngữ nghĩa Seq, bạn sẽ phải ở lại lười biếng tất cả các thời gian.

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]] 
+1

trong khi điều này sẽ làm việc, Seq.groupBy không phải là lười biếng và sẽ đánh giá đầy đủ các chuỗi đầu vào của nó khi phần tử đầu tiên được yêu cầu từ Seq.groupBy –

1

Điều này có vẻ rất thanh nha nhưng nó được câu trả lời đúng:

(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::[] 
+0

Có vẻ đầy hứa hẹn, nhưng làm cách nào để chuyển đổi seq > thành seq để sử dụng phương pháp này? – bytebuster

+0

Câu hỏi của OP yêu cầu giải pháp để hoạt động trên một chuỗi các chuỗi có độ dài thay đổi, và không phải là một chuỗi các n-tuple. – Asti

0

Dường như ma trận chuyển vị.

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 

Ngoài ra, bạn có thể áp dụng cùng một phương pháp cho seq, nhờ this answer cho Active mẫu thanh lịch:

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 

Xem thêm this answer để biết chi tiết kỹ thuật và hai tài liệu tham khảo: để PowerPack 's Microsoft.FSharp.Math.Matrix và phương pháp khác liên quan đến dữ liệu có thể thay đổi.

+0

Điều này đánh giá tất cả các trình tự háo hức mặc dù. 'Seq.ofList' không làm gì ngoài việc đưa danh sách vào' seq <'t> ', vì vậy không có nhiều ý nghĩa trong việc có chữ ký là' seq > '. – Asti

0

Đây là câu trả lời tương tự như @Asti, chỉ cần dọn dẹp một chút:

[[1;2;3]; [1;2;3]; [1;2;3]] 
    |> Seq.collect Seq.indexed 
    |> Seq.groupBy fst 
    |> Seq.map (snd >> Seq.map snd);; 
Các vấn đề liên quan