2013-04-22 8 views
5

प्रसंस्करण करना मेरे दूसरे दिन एक दिलचस्प साक्षात्कार प्रश्न था, जिसे मैंने वास्तव में संघर्ष किया था। (अत्यधिक महत्वाकांक्षी) spec मुझे लिखने के लिए आवश्यक है, सी # में, दो अलग-अलग डेटा धाराओं के लिए पार्सर्स। यहाँ पहली धारा की एक बना हुआ उदाहरण है:डेटा फीड प्रारूप

30=EUR/USD,35=3,50=ON,51=12.5,52=13.5,50=6M,51=15.4,52=16.2,50=1Y,51=17.2,52=18.3 

जहां 30 मुद्रा जोड़ी है, 35 tenors की संख्या है, और 50,51,52 तत्त्व, बोली रहे हैं और क्रमश: पूछो। बोली और पूछना वैकल्पिक है, लेकिन एक सही अवधि-बोली-पूछने वाले टुपल में कम से कम दो कीमतों में से एक होगा। उनके द्वारा प्रदान किए गए ढांचे कोड से संकेत मिलता है कि इस लाइन को पार्स करने का नतीजा 3 अलग-अलग ऑब्जेक्ट्स (डेटाइलेमेंट इंस्टेंस) होना चाहिए। मैं एक बदसूरत स्विच-कथन और लूप-आधारित कार्यान्वयन के साथ समाप्त हुआ जो मुझे यकीन नहीं है कि वास्तव में काम किया है।

इस तरह की धारा पढ़ने के लिए क्या तकनीकें हैं? मैंने रिकर्सन के साथ कुछ पता लगाने की कोशिश की, जिसे मैं सही नहीं मिला।

संपादित करें: @ evanmcdonnall के उत्तर (स्वीकृत) के आधार पर यहां पूरी तरह से संकलित और काम करने वाला कोड है, यदि यह किसी और के लिए उपयोगी है।

 List<DataElement> Parse(string row) 
    { 
     string currency=string.Empty; 
     DataElement[] elements = null; 
     int j = 0; 
     bool start = false; 
     string[] tokens = row.Split(','); 
     for (int i = 0; i < tokens.Length; i++) 
     { 
      string[] kv = tokens[i].Split('='); 

      switch (kv[0]) 
      { 
       case "30": 
        currency = kv[1]; 
        break; 
       case "35": 
        elements = new DataElement[int.Parse(kv[1])]; 
        break; 
       case "50": 
        if (start) 
         j++; 
        elements[j] = new DataElement() { currency = currency, tenor = kv[1] }; 
        start = true; 
        break; 
       case "51": 
        elements[j].bid = double.Parse(kv[1]); 
        break; 
       case "52": 
        elements[j].ask = double.Parse(kv[1]); 
        break; 
      } 
     } 
     return elements.ToList(); 
    } 

मुख्य अवधारणाओं हैं:

  • प्रत्येक पंक्ति में आइटम दोहराने की "आंतरिक लूप"
  • इंगित करने के लिए एक बूलियन ध्वज है के लिए एक अलग काउंटर है जब कि "आंतरिक पाश" शुरू होता है
  • "आंतरिक लूप" परिणामों को उस बिंदु पर संग्रहीत करने के लिए ऑब्जेक्ट्स की सरणी आवंटित करें जहां लंबाई ज्ञात है (यानी, टैग 50)
  • सादगी और स्पष्टता के लिए, एक ऐसा फ़ंक्शन है जो केवल एक ही पढ़ता है लाइन, फिर इसे एक अलग समारोह से कई बार कॉल करें।
+0

यह इस तरह नहीं दिखता है एक सीमांकित datastream, और न ही निश्चित चौड़ाई है। मुझे लगता है कि आपकी विधि उचित लगती है –

+0

तत्वों का क्रम हमेशा समान होता है? मेरा मतलब है कि पहले आपके पास मुद्रा जोड़ी होगी, फिर किरायेदारों की संख्या होगी, और उसके बाद किरायेदारों की संख्या के अनुरूप टुपल की सही संख्या होगी? – ppetrov

+1

@AndrewWalters: यह काफी लगातार '' '' – mellamokb

उत्तर

2

मुझे नहीं पता कि इसके बारे में क्या मुश्किल है। हालांकि, मुझे कोई समाधान नहीं दिख रहा है जो बहुत ही विशिष्ट, बेहतर है जो कई सशर्त समाधानों के साथ दिमाग में है।

सबसे पहले आप अल्पविरामों पर विभाजित होते हैं, फिर आप उन टोकन पर लूप करते हैं, जो आपको मुख्य मूल्य जोड़ी प्राप्त करने के लिए बराबर चिह्न पर विभाजित करते हैं। जब आप किसी आइटम को प्रारंभ/समाप्त करते हैं तो आपके पास प्रत्येक कुंजी और एक बूल के लिए जांच होती है। आप मुद्रा को पढ़ते हैं और प्रत्येक ऑब्जेक्ट के लिए इसका उपयोग करते हैं। आप कुंजी 35 पढ़ते हैं और पाते हैं कि 3 ऑब्जेक्ट्स हैं, इसलिए आप तीन ऑब्जेक्ट्स की एक सरणी आवंटित करते हैं, प्रत्येक में 3 गुण होते हैं; किरायेदार, बोली, और पूछो। जब आप 50 का सामना करते हैं तो आपको अपनी शुरुआत सही करनी चाहिए। यदि आप वहां हैं तो आप 50, 51, और 52 सेट करते हैं। नीचे कुछ नमूना कोड है;

string currency; 
    int j = 0; 
    bool start = false; 
    string[] tokens = line.Split(','); 
    for (int i =0; i < tokens.length; i++) 
    { 
     string[] kv = tokens[i].Split('=') 
     if (kv[0] == 30) 
      currency = kv[1] 
     elseif (kv[0] == 35) 
     { 
      DateElement[] elements = new DataElement[kv[1]]; 
     } 
     elseif (kv[0] == 50) 
     { 
      if (start) 
       j++; 
      start = true; // flip your flag after the condition so it works for element 0 
      elements[j].currency = currency; 
      elements[j].tenor = kv[1]; 
     } 
     elseif (kv[0] == 51) 
      elements[j].bid = kv[1]; 
     elseif (kv[0] == 52)  
      elements[j].ask = kv[1]; 
     // if these optional values aren't there we'll just fall back into the case for 50 
     // and everything will work as expected. 
    } 

कोड सुंदर नहीं हो सकता है, लेकिन तर्क काफी तुच्छ है और, यह मानते हुए लाइनों स्वरूप सही है, यह हमेशा काम करेंगे।

+1

मैंने यह नहीं कहा कि यह मुश्किल था, मैंने कहा कि मैं इसके साथ संघर्ष कर रहा हूं - उन दो बयानों के बीच एक बहुत ही स्पष्ट अंतर है :)। मैं देखता हूं कि आपके कोड की तरह मैंने जो लाइन ली है, सिवाय इसके कि आप स्पष्ट रूप से एक अलग गिनती चर (जे) रखते हैं, जबकि मैंने लूप वैरिएबल (i) के साथ मेरा संयोजन करने की कोशिश की है, और टैग 35 के दौरान तत्व सरणी आवंटित करने का आपका दृष्टिकोण आता है एक अच्छा है। धन्यवाद। – endian

+0

@endian मेरी माफ़ी। इस तरह की स्ट्रिंग प्रसंस्करण पहले कुछ मुश्किल है लेकिन इसके बाद आप इसका उपयोग करने के बाद, यह बहुत ही नियमित हो जाती है। – evanmcdonnal

+0

क्या आपको अपना 'जे' वैरिएबल वापस 0 पर सेट करने की आवश्यकता है जब आपको नया 35 = मिलता है? – endian

0

30 = EUR/USD, 35 = 3,50 = चालू, 51 = 12.5,52 = 13.5,50 = 6 एम, 51 = 15.4,52 = 16.2,50 = 1 वाई, 51 = 17.2,52 = 18.3

मुझे आज़माएं। मैं सी # कोड लिखने, बस अपना दृष्टिकोण का एक सिंहावलोकन

मैं इस 2 खंडों Chain1 = {P0, पी 1} और Chain2 = में टूट जाएगा {P2 ...... पीएन}

तोड़ दे रही है नहीं कर रहा हूँ पी 1 से मूल्य के आधार पर समान रूप से चेन 2। अल्पविराम की स्थिति के आधार पर।

substr=Chain.substring(0,Chain2.IndexOf(",", P1=3)); 

हम एक Tuple क्लास संग्रह बना सकते हैं -

here either i can use regex to split the string or simple substring and indexof("=") to extract value 

var seg= new Tuple<string, int, int, >("ON", 12.5, 13.5); 
संबंधित मुद्दे