2012-10-07 34 views
5

में मान लें कि मेरे पास अनुक्रमों का अनुक्रम है, उदा।Pivot या ज़िप एक seq <seq<'a>> F #

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

क्या पिवट या इस क्रम ज़िप इसलिए मैं बजाय है करने के लिए सबसे अच्छा तरीका है वहाँ अंतर्निहित IEnumerator<_> प्रकार के हेरफेर का सहारा के बिना ऐसा करने का एक सुबोध रास्ता है,?

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

है

स्पष्टीकरण के लिए, ये seq<seq<int>> ऑब्जेक्ट्स हैं। प्रत्येक अनुक्रम (आंतरिक और बाहरी दोनों) में कई वस्तुएं हो सकती हैं।

+0

तो तुम चाहते हो एक तत्व द्वारा एक मैट्रिक्स हस्तांतरण या समूह करने के लिए - यह बहुत नहीं है स्पष्ट। एक लंबे इनपुट के लिए एक उदाहरण अच्छा होगा। –

+1

संभावित डुप्लिकेट [मैं एफ # में एक ज़िप-जैसे फ़ंक्शन कैसे लिखूं?] (Http://stackoverflow.com/questions/11770441/how-do-i-write-a-zipn-like-function-in-f) – Daniel

उत्तर

3

यदि आप एक समाधान के लिए जा रहे हैं जो अर्थात् सेक है, तो आपको हर समय आलसी रहना होगा।

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

जबकि यह काम करेगा, Seq.groupB आलसी नहीं है और Seq.groupBy से पहले तत्व से अनुरोध किए जाने के बाद पूरी तरह से अपने इनपुट अनुक्रमों का मूल्यांकन करेगा –

1

यह बहुत असजीला लगता है, लेकिन यह सही जवाब हो जाता है:

(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

यह आशाजनक लग रहा है, लेकिन मैं इस विधि का उपयोग करने के लिए seq > seq को कैसे परिवर्तित करूं? – bytebuster

+0

ओपी के प्रश्न को चर की लंबाई के अनुक्रमों के अनुक्रम पर संचालित करने के लिए समाधान की आवश्यकता होती है, न कि एन-टुपल्स का अनुक्रम। – Asti

0

यह मैट्रिक्स स्थानांतरण तरह दिखता है।

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 तकनीकी जानकारी के लिए और दो संदर्भ:

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 लिए एक सुरुचिपूर्ण सक्रिय पैटर्न के लिए भी धारण कर सकता पॉवर के लिए Microsoft.FSharp.Math.Matrix और अभी तक म्यूटेबल डेटा शामिल एक और विधि शामिल है।

+0

यह उत्सुकता से सभी अनुक्रमों का मूल्यांकन करता है। 'Seq.ofList' कुछ भी नहीं करता है लेकिन सूची को 'seq <'t>' पर डाला गया है, इसलिए 'seq >' के रूप में हस्ताक्षर करने में बहुत अधिक अर्थ नहीं है। – Asti

0

यह @Asti रूप में एक ही जवाब है, बस साफ एक छोटे से:

[[1;2;3]; [1;2;3]; [1;2;3]] 
    |> Seq.collect Seq.indexed 
    |> Seq.groupBy fst 
    |> Seq.map (snd >> Seq.map snd);;