2009-05-21 29 views
10

मुझे सी # पसंद है, मुझे ढांचे से प्यार है, और मुझे जितना संभव हो सीखना पसंद है। आज मैंने सी # में LINQ के बारे में लेख पढ़ना शुरू कर दिया और मुझे शुरुआत के लिए कुछ भी अच्छा नहीं मिला जो कभी भी अपने जीवन में एसक्यूएल के साथ काम नहीं करता था।शुरुआती के लिए LINQ

मुझे this आलेख बहुत उपयोगी पाया गया और मैं इसके छोटे हिस्सों को समझ गया, लेकिन मैं और उदाहरण प्राप्त करना चाहता हूं।

इसे पढ़ने के बाद, मैंने LINQ का उपयोग मेरे एक समारोह में करने की कोशिश की, लेकिन मैं असफल रहा।

private void Filter(string filename) 
    { 
     using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
     { 
      using(TextReader reader = File.OpenText(filename)) 
      { 
       string line; 
       while((line = reader.ReadLine()) != null) 
       { 
        string[] items = line.Split('\t'); 
        int myInteger = int.Parse(items[1]); 
        if (myInteger == 24809) writer.WriteLine(line); 
       } 
      } 
     } 
    } 

यही मैंने किया और यह काम नहीं किया, परिणाम हमेशा झूठा था।

private void Filter(string filename) 
    { 
     using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
     { 
      using(TextReader reader = File.OpenText(filename)) 
      { 
       string line; 
       while((line = reader.ReadLine()) != null) 
       { 
        string[] items = line.Split('\t'); 
        var Linqi = from item in items 
           where int.Parse(items[1]) == 24809 
           select true; 
        if (Linqi == true) writer.WriteLine(line); 
       } 
      } 
     } 
    } 

मैं दो बातों के लिए पूछ रहा हूँ:

  1. कैसे समारोह के रूप में ज्यादा Linq संभव के रूप में उपयोग करते हुए की तरह लग रहे हैं?
  2. लिंक के बारे में एक वेबसाइट/पुस्तक/लेख, लेकिन कृपया ध्यान दें कि मैं एसक्यूएल/लिनक में एक सभ्य शुरुआत कर रहा हूं।

अग्रिम धन्यवाद!

+0

बस एक टिप्पणी करता है। आपका "जहां int.Parse (आइटम [1]) == 2480 9" प्रत्येक पंक्ति के लिए प्रत्येक कॉलम में दूसरे अक्षर को देख रहा है। –

उत्तर

19

खैर एक एक चीज जो लाइन से लाइन पढ़ने के लिए आपके नमूना को अधिक "LINQy" बनाती है, IEnumerable<string> है।

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.IO; 

public sealed class LineReader : IEnumerable<string> 
{ 
    readonly Func<TextReader> dataSource; 

    public LineReader(string filename) 
     : this(() => File.OpenText(filename)) 
    { 
    } 

    public LineReader(Func<TextReader> dataSource) 
    { 
     this.dataSource = dataSource; 
    } 

    public IEnumerator<string> GetEnumerator() 
    { 
     using (TextReader reader = dataSource()) 
     { 
      string line; 
      while ((line = reader.ReadLine()) != null) 
      { 
       yield return line; 
      } 
     } 
    } 


    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

अब आप उपयोग कर सकते हैं:: यहाँ MiscUtil से मेरी LineReader वर्ग के कुछ सरल संस्करण है

var query = from line in new LineReader(filename) 
       let items = line.Split('\t') 
       let myInteger int.Parse(items[1]); 
       where myInteger == 24809 
       select line; 

    using (TextWriter writer = File.CreateText(Application.StartupPath 
               + "\\temp\\test.txt")) 
    { 
     foreach (string line in query) 
     { 
      writer.WriteLine(line); 
     } 
    } 

ध्यान दें कि यह शायद अधिक let खंड नहीं करने के लिए कुशल होगा:

var query = from line in new LineReader(filename) 
       where int.Parse(line.Split('\t')[1]) == 24809 
       select line; 

किस बिंदु पर आप इसे "डॉट नोटेशन" में उचित रूप से कर सकते हैं:

var query = new LineReader(filename) 
         .Where(line => int.Parse(line.Split('\t')[1]) == 24809); 

हालांकि, मैं अब तक मूल प्रश्न की पठनीयता :)

+1

@ जॉन, मुझे आपकी किताब मिल गई है, कला का इतना टुकड़ा होना वास्तव में बहुत अच्छा है। मेरे पास एक और सवाल है - क्या आप मुझे वह पृष्ठ बता सकते हैं जहां आप अपनी पुस्तक में LINQ गहरे विवरण में समझाते हैं? –

+0

आपका बहुत तेज़ तेज जॉन। :) –

+0

इसी तरह के नोट पर, यहां स्ट्रीम पोस्ट करने के लिए ब्लॉग पोस्ट है: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2009/01/30/making-streams-enumerable.aspx – plinth

5

एक प्रारंभिक बिंदु के रूप में एक वेबसाइट के लिए, आप की कोशिश कर सकते Hooked on LINQ

संपादित:
मूल साइट अब मृत होने का (डोमेन बिक्री के लिए है) प्रकट होता है।

यहाँ पिछले संस्करण की इंटरनेट संग्रह है: https://web.archive.org/web/20140823041217/http://www.hookedonlinq.com/

6

101 LINQ Samples निश्चित रूप से उदाहरण का एक अच्छा संग्रह है। LINQ के साथ खेलने के लिए LINQPad भी एक अच्छा तरीका हो सकता है।

-1

सिर्फ अगर Linqi सच है की जाँच नहीं कर सकते हैं ... Linqi एक IEnumerable<bool> है (इस मामले में) तो Linqi.First() == true

की तरह जांच करनी है

यहाँ एक छोटा सा उदाहरण है:

string[] items = { "12121", "2222", "24809", "23445", "24809" }; 

         var Linqi = from item in items 
            where Convert.ToInt32(item) == 24809 
            select true; 
         if (Linqi.First() == true) Console.WriteLine("Got a true"); 

तुम भी Linqi से अधिक पुनरावृति सकता है, और मेरे उदाहरण में संग्रह में 2 आइटम नहीं है।

+0

मेरे फ़ंक्शन में जितना संभव हो उतना लिनक का उपयोग करने का एक उदाहरण बहुत सराहना की जाएगी। :) –

+0

प्यार जब नीचे वोट के लिए कोई स्पष्टीकरण नहीं है ... यह एक आवश्यकता होनी चाहिए। – CSharpAtl

+0

चूंकि प्रश्न SQL और LINQ के बारे में था, इसलिए मैंने अपने कोड को पूरी तरह से लिखने की कोशिश नहीं की थी। – CSharpAtl

0

अगर मैं LINQ का उपयोग कर अपने फिल्टर समारोह के पुनर्लेखन के लिए था, जहां संभव हो, यह इस तरह दिखना चाहते हैं:

private void Filter(string filename) 
{ 
    using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
    { 
     var lines = File.ReadAllLines(filename); 
     var matches = from line in lines 
         let items = line.Split('\t') 
         let myInteger = int.Parse(items[1]); 
         where myInteger == 24809 
         select line; 

     foreach (var match in matches) 
     { 
      writer.WriteLine(line) 
     } 
    } 
} 
+0

हम्म ... परिचित लग रहा है :) (हालांकि यह सुनिश्चित नहीं है कि जब आप लाइन मुद्रित करना चाहते हैं तो आप int का चयन क्यों कर रहे हैं) –

+0

ध्यान दें कि एक ही समय में सभी पंक्तियों को पढ़ना एक सीमित कारक है - और अनावश्यक रूप से। (मेरा जवाब देखें :) –

+0

यह बड़ी फ़ाइलों के लिए एक मुद्दा है, जाहिर है। जॉन स्कीट का जवाब बेहतर है ... श्वास, और नया क्या है। :-) –

0

पहले सवाल का जवाब करने के लिए, स्पष्ट रूप से बहुत ज्यादा कारण LINQ तरीके से उपयोग करने के लिए नहीं है आप अभ्यास के अलावा उपरोक्त कार्य में सुझाव देते हैं। असल में, यह संभवतः फ़ंक्शन को पढ़ने के लिए कठिन बनाता है।

LINQ एक तत्व की तुलना में संग्रह पर परिचालन करने में अधिक उपयोगी है, और मैं इसके बजाय इस तरह इसका उपयोग करूंगा। तो, यहाँ समारोह में संभव के रूप मेंके रूप में ज्यादा LINQ का उपयोग करने में मेरी प्रयास है (दक्षता का कोई जिक्र नहीं करते हैं और मैं इस तरह स्मृति में पूरी फ़ाइल नहीं पढ़ने का सुझाव कर ):

private void Filter(string filename) 
{ 
    using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
    { 
     using(TextReader reader = File.OpenText(filename)) 
     { 
      List<string> lines; 
      string line; 
      while((line = reader.ReadLine()) != null) 
       lines.Add(line); 

      var query = from l in lines 
         let splitLine = l.Split('\t') 
         where int.Parse(splitLine.Skip(1).First()) == 24809 
         select l; 

      foreach(var l in query)    
       writer.WriteLine(l); 
     } 
    } 
} 
1

प्रथम पसंद करते हैं, मैं इस पद्धति को लागू होगा:

private IEnumerable<string> ReadLines(StreamReader reader) 
{ 
    while(!reader.EndOfStream) 
    { 
     yield return reader.ReadLine(); 
    } 
} 

फिर, मैं इसे उपयोग करने के लिए मुख्य विधि refactor होगा। मैं एक ही ब्लॉक के ऊपर दोनों using बयान रखा, और भी items[1] सुनिश्चित करने के लिए एक सीमा की जांच जोड़ा विफल नहीं हुआ:

private void Filter(string fileName) 
{ 
    using(var writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt")) 
    using(var reader = File.OpenText(filename)) 
    { 
     var myIntegers = 
      from line in ReadLines(reader) 
      let items = line.Split('\t') 
      where items.Length > 1 
      let myInteger = Int32.Parse(items[1]) 
      where myInteger == 24809 
      select myInteger; 

     foreach(var myInteger in myIntegers) 
     { 
      writer.WriteLine(myInteger); 
     } 
    } 
} 
+0

टेक्स्ट रीडर का यह तरीका किस तरह से निपटता नहीं है? यह एक प्रयोग कथन में है। –

+0

(ध्यान दें कि यह * इसे तब नहीं सुलझाएगा जब कोई कॉलर मैन्युअल रूप से MoveNext() को कॉल करता है और फिर पुनरावर्तक को त्याग देता है, लेकिन कॉल को स्वचालित रूप से निपटाना।) –

+0

आप सही हैं, मैं गलत पढ़ता हूं। आप कन्स्ट्रक्टर का उपयोग नहीं कर रहे हैं जो एक Func लेता है। मेरा मतलब था कि जब आप उस फ़ंक्शन का उपयोग करते हैं, तो LineReader क्लास TextReader इंस्टेंस के जीवनकाल को पूरी तरह से समाहित नहीं करता है। –

3

यदि आप कर रहे हैं एक किताब के बाद, मैं LINQ in actionManning Publications से पाया एक अच्छी जगह शुरू करने के लिए।

1

Linq पुस्तकों के लिए के रूप में, मैं सिफारिश करेंगे:

http://www.ebookpdf.net/screen/cover2/51n4fa2xxvl_083.jpg     http://www.diesel-ebooks.com/mas_assets/full/0321564189.jpg

दोनों कि Linq में ड्रिल विस्तार से उत्कृष्ट पुस्तकें हैं।

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 

namespace LinqDemo 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var baseDir = AppDomain.CurrentDomain.BaseDirectory; 
      File.WriteAllLines(
       Path.Combine(baseDir, "out.txt"), 
       File.ReadAllLines(Path.Combine(baseDir, "in.txt")) 
        .Select(line => new KeyValuePair<string, string[]>(line, line.Split(','))) // split each line into columns, also carry the original line forward 
        .Where(info => info.Value.Length > 1) // filter out lines that don't have 2nd column 
        .Select(info => new KeyValuePair<string, int>(info.Key, int.Parse(info.Value[1]))) // convert 2nd column to int, still carrying the original line forward 
        .Where(info => info.Value == 24809) // apply the filtering criteria 
        .Select(info => info.Key) // restore original lines 
        .ToArray()); 
     } 
    } 
} 

ध्यान दें कि मैं अल्प विराम द्वारा सीमांकित कॉलम के लिए अपने टैब-सीमांकित-कॉलम बदल (आसान:

अभी तक के रूप में बहुत LINQ के रूप में संभव विषय के लिए एक और भिन्नता को जोड़ने के लिए, यहाँ मेरी ले रहा है मेरे संपादक में लेखक के लिए जो टैब को रिक्त स्थानांतरित करता है ;-))। इस कार्यक्रम के एक इनपुट फ़ाइल सापेक्ष चलाया जाता है:

A1,2 
B,24809,C 
C 

E 
G,24809 

उत्पादन होगा:

B,24809,C 
G,24809 

आप "File.ReadAllLines" और "File.WriteAllLines" बदल कर भी इस समाधान की स्मृति आवश्यकताओं को बेहतर बना सकते जॉन स्कीट के लाइन रीडर (और लाइनवाइटर एक समान नस में, आईनेमरेबल लेते हुए और प्रत्येक लौटाई गई वस्तु को आउटपुट फाइल में एक नई लाइन के रूप में लिखते हैं)।यह उपर्युक्त समाधान को "सरणी के रूप में स्मृति में प्राप्त करने, उन्हें फ़िल्टर करने, परिणाम के लिए स्मृति में एक और सरणी बनाने के लिए, और परिणामस्वरूप फ़ाइल को इनपुट फ़ाइल से लाइनों को एक-एक करके पढ़ने के लिए", और यदि वह लाइन हमारे मानदंडों को पूरा करती है, इसे तुरंत आउटपुट फ़ाइल में लिखें "(पाइपलाइन दृष्टिकोण)।

1

मैं इस लेख LINQ जो .NET 3.0 & 3.5 में लाया इतने सारे नए निर्माणों पर आधारित है समझने के लिए अत्यंत महत्वपूर्ण हो पाया:

मैं आपको चेतावनी देता हूँ कि यह एक लंबे समय तक पढ़ा है, लेकिन अगर तुम सच में समझने के लिए Linq है चाहते हैं और मेरा मानना ​​है कि यह जरूरी है

http://blogs.msdn.com/ericwhite/pages/FP-Tutorial.aspx

मुबारक पढ़ने

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