2012-12-31 14 views
6

मैं 30 000 लाइनों के साथ csv फ़ाइल है। मुझे कई स्थितियों के आधार पर कई मूल्यों का चयन करना है, इसलिए कई लूपों और "अगर है" के लिए मैंने linq का उपयोग करने का निर्णय लिया है। मैंने सीएसवी पढ़ने के लिए कक्षा लिखी है। यह linq के साथ उपयोग करने के लिए IENumerable लागू करता है। यह मेरा गणक है:LINQ में खोज विधि को बदलना संभव है?

class CSVEnumerator : IEnumerator 
{ 

    private CSVReader _csv; 

    private int _index; 

    public CSVEnumerator(CSVReader csv) 
    { 
     _csv = csv; 
     _index = -1; 
    } 

    public void Reset(){_index = -1;} 


    public object Current 
    { 
     get 
     { 
      return new CSVRow(_index,_csv); 
     } 
    } 


    public bool MoveNext() 
    { 
     return ++_index < _csv.TotalRows; 
    } 

} 

यह काम कर रहा है, लेकिन यह धीमा है। मान लीजिए कि मैं कॉलम ए में अधिकतम मूल्य 100 रेंज में चुनना चाहता हूं; 150 पंक्ति।

max = (from CSVRow r in csv where r.ID > 100 && r.ID < 150 select r).Max(y=>y["A"]); 

यह काम करेंगे, लेकिन 30 000 के बजाय 48. पंक्तियों जैसा कि मैंने कहा, मैं पाश इस्तेमाल कर सकते हैं, लेकिन केवल इस उदाहरण मामले में, की स्थिति "क्रूर" कर रहे हैं में अधिकतम मूल्य के लिए LINQ खोजें :)

वहाँ LINQ संग्रह खोज ओवरराइड करने के लिए कोई तरीका है। कुछ ऐसा: मेरे गणक पर उपयोग की गई क्वेरी में देखें, देखो, "जहां" में "lin" में कोई भी लिनक्स स्थितियां "पंक्ति आईडी फ़िल्टर" है और इस पर आधारित एक और डेटा दें।

मैं एक सरणी/संग्रह करने के लिए डेटा का हिस्सा कॉपी नहीं करना चाहते हैं और समस्या मेरी सीएसवी रीडर में नहीं है। आईडी द्वारा प्रत्येक पंक्ति तक पहुंच तेजी से होती है, केवल समस्या तब होती है जब आप उनमें से सभी 30 000 तक पहुंचते हैं। किसी भी मदद की सराहना की :-)

+1

BTW है, तो मैं भी ऐसा ही किया।), आप को लागू करना चाहिए 'IEnumerable '। – SLaks

+0

यह कैसे कार्यान्वित किया जाता है -> 'नया सीएसवीआरओ (_index, _csv) '। यादृच्छिक पहुंच या अनुक्रमिक पहुंच? – Tilak

+1

क्या आप सुनिश्चित हैं कि ऑब्जेक्ट्स के लिए linq आपके सभी रिकॉर्ड पर अधिकतम लागू होता है न केवल इन 48? अजीब, यह अनुक्रमिक रूप से ऑपरेटरों को लागू करना चाहिए। मेरा अनुमान है कि आपका गणक धीमा है। –

उत्तर

2

यदि आप इस कुशलता के लिए LINQ का उपयोग करने में सक्षम होना चाहते हैं, तो आपको SQL डेटाबेस के लिए विभिन्न LINQ प्रदाताओं की तुलना में समान (लेकिन बहुत आसान) तरीके से expression trees का उपयोग करना होगा। जबकि करने योग्य, मुझे लगता है कि यह इतना आसान काम के लिए काफी कोड होगा।

इस कारण से

, मुझे लगता है कि एक बेहतर समाधान पंक्तियों आप चाहते हैं (और फिर संभवतः परिणाम के साथ काम करने के लिए LINQ का उपयोग करें) का चयन करने के लिए एक अलग विधि का उपयोग करना होगा।

इसके अलावा, कई कार्य है कि (अपने मूल कोड और मेरी संशोधन सहित) संग्रह लौट iterator methods का उपयोग करके सरल किया जा सकता।

तो, अपने कोड कुछ इस तरह दिखाई दे सकता है:

public static IEnumerable<CSVRow> GetRows(
    this CSVReader reader, int idGreaterThan, int idLessThan) 
{ 
    for (int i = idGreaterThan + 1; i < idLessThan; i++) 
    { 
     yield return new CSVRow(reader, i); 
    } 
} 

यहाँ, यह CSVReader के लिए एक विस्तार विधि है, लेकिन एक और समाधान (उस वर्ग पर जैसे वास्तविक विधि) आप के लिए अधिक उपयुक्त हो सकता है।

आपका उदाहरण तो कुछ ऐसा दिखाई देगा:

max = csvReader.GetRows(100, 150).Max(y => y["A"]); 

(इसके अलावा, मैं यह अजीब है कि आप सीमा 100 और 150 है जब, आप वास्तव में 101 और 149 के बीच पंक्तियों लेकिन मैं तुम्हें यह सोचते कर रहा हूँ करना चाहते हैं उस के लिए एक कारण

+0

यह वही है जो मुझे चाहिए, धन्यवाद :-) 100 और 150 समस्या दिखाने के लिए केवल उदाहरण था, अगर मैं वास्तविक स्थिति पोस्ट करता हूं, तो मुझे यह समझाना होगा कि चर कहां से आते हैं, जो डेटाटाइप आदि हैं ... –

1

जहां तक ​​LINQ का संबंध है, r.ID केवल एक मान है जिसे फ़िल्टर किया जा रहा है और इसलिए अधिकतम 30k लाइनों को मैक्स ऑपरेशन में उपयोग के लिए माना जाता है। यदि यह एक पंक्ति सूचकांक है, जो यहां मामला प्रतीत होता है, तो आप सभी 30k पंक्तियों की तुलना से बचने के लिए Skip और Take का उपयोग कर सकते हैं।

max = csv.Skip(100).Take(50).Max(y => y["A"]); 
+0

लेकिन यह अभी भी 150 पंक्तियों, 50 के आइसटेड को फिर से चलाएगा। इसलिए, यदि श्रेणी 2 9, 000-29050 थी, तो आप 2 9 050 पंक्तियों को फिर से सक्रिय करेंगे, जो बहुत ही अप्रभावी है। – svick

+0

@svik: यदि आप पहले 2 9 000 को छोड़ देते हैं तो आपका सीएसवीआरडर कैसे जानता है कि वह कौन सी पंक्ति है? इससे पहले कि आप सही लाइनों का चयन करें, आपको अभी भी उन सभी को पढ़ने की जरूरत है। मुझे लगता है कि सीएसवीआरडर कार्यान्वयन अक्षम है। इसे पहले से पढ़ी गई लाइनों को कैश करना चाहिए, फिर लगभग सभी प्रश्न तेजी से होंगे। –

+0

@AloisKraus मुझे नहीं पता कि 'सीएसवीआरडर' कैसे कार्यान्वित किया गया है, लेकिन सवाल कहता है कि यह किसी भी पंक्ति को कुशलतापूर्वक पुनर्प्राप्त करता है। – svick

0

@DougM मूल्यांकन के आदेश के बारे में सही है, लेकिन इस मामले में मैं क्या होगा किसी भी "सूचकांक" क्षेत्रों के लिए एक बार प्रारंभ पर हिट लेने के लिए और लुकअप उत्पन्न है: मूल रूप से, पूर्व मानचित्र गणना (शब्दकोश पंक्ति पंक्ति पंक्ति का शब्दकोश। उस ने कहा, यह केवल उपयोगी होगा यदि आपके पास दिए गए इंडेक्स फ़ील्ड के लिए कई बार बार-बार पूछे जाने वाले प्रश्न हैं।

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