2010-09-23 16 views
5

मैं (tuples के) दो दृश्यों जिस पर मैं क्या करने की जरूरत है एक में शामिल होने:मैं Enumerable कैसे कॉल करूं। F # से जुड़ें?

  • Seq 1: [(City1 * Pin1), (City2 * Pin2), (City1 * Pin3), (City1 * pin4)]
  • Seq 2: [(Pin1 * productÃ), (Pin2 * ProductB), (Pin1 * ProductC), (Pin2 * productÃ)]
(tuples के) अनुक्रम में

:

  • [(सिटी 1 * उत्पाद ए), (सिटी 2 * उत्पाद बी), (सिटी * उत्पादसी), (City2 * उत्पाद ए) ...]

सी # में मैं का उपयोग कर Linq में शामिल होने की तरह विस्तार विधि ऐसा कर सकता है:

seq1.Join(seq2, t => t.Item2, t=> t.Item1, 
    (t,u) => Tuple.Create(t.Item1, u.Item2)) 

मैं कैसे एफ # में यह पूरा करते हैं? मैं वहां सेक पर शामिल नहीं हो सकता।

+0

मैं एक कुशल कार्यान्वयन की तलाश में हूं क्योंकि उत्पाद/पिन की यह सूची काफी लंबी है। लिंक मेरे लिए ठीक काम करता प्रतीत होता है, लेकिन इसे एफ # से काम करने के लिए नहीं मिल सकता है। –

+0

क्या एफ # अनुक्रम 'आईनेमेरेबल' को भी लागू करते हैं? यदि वे नहीं करते हैं, तो आप LINQ का उपयोग नहीं कर सकते हैं। –

+0

हां, वे IENumerable लागू करते हैं। –

उत्तर

6

संपादित करें: असल में, तुम सिर्फ LINQ का उपयोग कर सकते हैं:

> open System.Linq;; 
> let ans = seq1.Join(seq2, (fun t -> snd t), (fun t -> fst t), (fun t u -> (fst t, snd u)));; 

एफ # के देशी Seq कार्यों का उपयोग क्यों नहीं? यदि आप at the docs और at this question देखते हैं तो आप आसानी से LINQ के बजाय इनका उपयोग कर सकते हैं। उदाहरण के लिए Seq.map2 समारोह लें:

> let mapped = Seq.map2 (fun a b -> (fst a, snd b)) seq1 seq2;; 

val it : seq<string * string> = 
    seq [("city1", "product1"); ("city2", "product2")] 

आप देना चाहिए कि आप क्या चाहते हैं, जहां seq1 और seq2 अपने पहले और दूसरे दृश्यों रहे हैं।

+0

शहर पिन और पिन के साथ कई लोगों के लिए एक होगा जो उत्पादों के साथ कई लोगों के लिए होगा। क्या आप समझा सकते हैं कि यह कैसे काम करेगा? –

+0

क्या आपका मतलब है कि आप '[(सिटी 1 * पिन 1 * पिन 2), (सिटी 2 * पिन 2)]' और '[(पिन 1 * उत्पाद ए), (पिन 2 * उत्पाद बी * उत्पादक)]' यानी टुपल्स का उपयोग कर सकते हैं जो 2 से अधिक तत्वों? –

+0

नहीं, मेरा मतलब है कि मेरे पास समान शहर और अलग पिन के अनुक्रम में कई आइटम हो सकते हैं। इसी तरह, मेरे पास एक ही पिन और अलग-अलग उत्पाद या सीईसी 2 के विपरीत कई आइटम हो सकते हैं। टुपल में हमेशा 2 आइटम होंगे। –

2

एफ # इंटरएक्टिव सत्र:

> let seq1 = seq [("city1", "pin1"); ("city2", "pin2")];; 

val seq1 : seq<string * string> = [("city1", "pin1"); ("city2", "pin2")] 

> let seq2 = seq [("pin1", "product1"); ("pin2", "product2")];; 

val seq2 : seq<string * string> = [("pin1", "product1"); ("pin2", "product2")] 

> Seq.zip seq1 seq2;; 
val it : seq<(string * string) * (string * string)> = 
    seq 
    [(("city1", "pin1"), ("pin1", "product1")); 
    (("city2", "pin2"), ("pin2", "product2"))] 
> Seq.zip seq1 seq2 |> Seq.map (fun (x,y) -> (fst x, snd y));; 
val it : seq<string * string> = 
    seq [("city1", "product1"); ("city2", "product2")] 

इसके अलावा, आप और दृश्यों पर LINQ क्वेरी का उपयोग करने के लिए, बस सुनिश्चित करें कि आप System.Linq विधानसभा के लिए एक संदर्भ है हो सक्षम होना चाहिए एक namespace खोला open System.Linq

अद्यतन: एक जटिल परिदृश्य इस प्रकार आप अनुक्रम भाव का उपयोग कर सकते में:

open System 

let seq1 = seq [("city1", "pin1"); ("city2", "pin2"); ("city1", "pin3"); ("city1", "pin4")] 
let seq2 = seq [("pin1", "product1"); ("pin2", "product2"); ("pin1", "product3"); ("pin2", "product1")] 

let joinSeq = seq { for x in seq1 do 
         for y in seq2 do 
          let city, pin = x 
          let pin1, product = y 
          if pin = pin1 then 
           yield(city, product) } 
for(x,y)in joinSeq do 
    printfn "%s: %s" x y 

Console.ReadKey() |> ignore 
+0

मेरे सामने 3 सेकंड! लिंक जोड़ना नहीं चाहिए था ... –

+0

शहरों में एक से अधिक पिन होंगे और पिन उत्पादों के साथ कई होंगे। –

+0

तो, अंतिम आदेश क्या करता है: पिछले आदेश के रूप में tuples के जोड़े की एक सूची बनाएं (Seq.zip), फिर इस सूची को नए पर मानचित्र करें, पहले tuple (fst x) का पहला तत्व प्राप्त करें और दूसरा तत्व दूसरे tuple (एसएनडी वाई) के। –

2

मुझे लगता है कि यह बिल्कुल स्पष्ट नहीं है कि आप क्या उम्मीद कर रहे हैं, इसलिए उत्तर थोड़ा उलझन में हैं। आपके उदाहरण को दो तरीकों से व्याख्या किया जा सकता है (या तो ज़िप या में शामिल होने के रूप में) और वे नाटकीय रूप से भिन्न हैं।

  • ज़िप करना: आप एक ही लंबाई की दो सूचियां है और आप correspoding आइटम (जैसे दूसरी सूची से 1 आइटम के साथ पहली सूची से 1 आइटम संरेखित करने के लिए चाहते हैं, 2 के साथ पहली सूची से 2 आइटम दूसरी सूची, आदि से आइटम ..), फिर List.zip या List.map2 का उपयोग करने वाले उत्तरों को देखें।

    हालांकि, इसका मतलब यह होगा कि सूचियों को पिन और पिन द्वारा क्रमबद्ध किया जाता है।उस स्थिति में आपको Join और यहां तक ​​कि सी #/LINQ में उपयोग करने की आवश्यकता नहीं है, आप Zip एक्सटेंशन विधि का उपयोग कर सकते हैं।

  • शामिल हो रहा है: यदि सूचियों में अलग-अलग लंबाई हो सकती है, तो पिन को सॉर्ट नहीं किया जा सकता है या अद्वितीय नहीं है, तो आपको वास्तविक जुड़ाव लिखना होगा। Artem कश्मीर से कोड का एक सरलीकृत संस्करण इस प्रकार दिखाई देगा:

    seq { for city, pin1 in seq1 do 
         for pin2, product in seq2 do 
          if pin1 = pin2 then yield city, product } 
    

    यह LINQ में Join की तुलना में कम कुशल हो सकता है, क्योंकि यह seq1 में हर आइटम के लिए seq2 में सभी आइटम के माध्यम से लूप होता है, तो जटिलता है O(seq1.Length * seq2.Length)। मुझे यकीन नहीं है, लेकिन मुझे लगता है कि Join कुछ हैशिंग का उपयोग अधिक कुशल होने के लिए कर सकता है। ,

    (seq1, seq2) 
        ||> Seq.join snd fst 
        |> Seq.map (fun (t, u) -> fst t, snd u) 
    

अंत में यदि आप जानते हैं कि वास्तव में एक है कि वहाँ:

open System.Linq 
module Seq = 
    let join (seq1:seq<_>) seq2 k1 k2 = 
    seq1.Join(seq2, (fun t -> k1 t), (fun t -> k2 t), (fun t u -> t, u)) 

तो फिर तुम कुछ इस तरह लिख सकते हैं: इसके बजाय Join विधि सीधे का उपयोग कर के, मैं शायद एक छोटे से सहायक परिभाषित करेगा प्रत्येक उत्पाद के लिए अद्वितीय शहर (अनुक्रमों में समान लंबाई होती है और पिन दोनों में अद्वितीय होते हैं), तो आप पिन द्वारा दोनों अनुक्रमों को क्रमबद्ध कर सकते हैं और फिर zip का उपयोग कर सकते हैं - यह join (विशेष रूप से यदि आप रख सकते हैंअनुक्रम कुछ पुराने परिचालनों से क्रमबद्ध)।

+0

हाय, मैं एक जॉइन (क्रॉस उत्पाद) चाहता था और इसे LINQ में एक शब्दकोश का उपयोग करके कार्यान्वित किया गया था जो इसे तेज़ी से बनाता है। –

संबंधित मुद्दे