2009-12-23 4 views
108

यह सिर्फ सामान्य ज्ञान के लिए:दोहराएं सी # में दो सूचियाँ या एक foreach बयान के साथ सरणी

अगर मैं दो है, मान लें, सूची, और मैं एक ही foreach पाश के साथ दोनों पुनरावृति करना चाहते हैं, हम कर सकते हैं वो करें?

संपादित

बस स्पष्ट करने के लिए, मैं यह करने के लिए चाहता था:

List<String> listA = new List<string> { "string", "string" }; 
List<String> listB = new List<string> { "string", "string" }; 

for(int i = 0; i < listA.Count; i++) 
    listB[i] = listA[i]; 

लेकिन एक foreach के साथ =)

+7

महत्वपूर्ण यहां शब्द "ज़िप" है। –

+3

क्या आप दो सूचियों को दोहराना चाहते हैं _in parallel_? या आप पहली सूची को फिर से शुरू करना चाहते हैं, और फिर दूसरा (एक ही कथन के साथ)? –

+0

मुझे लगता है कि आपका तरीका ज़िप – Alexander

उत्तर

189

यह एक Zip आपरेशन के रूप में जाना जाता है और में समर्थन किया जाएगा .NET 4.

इसके साथ, आप कुछ लिखने में सक्षम होंगे जैसे:

var numbers = new [] { 1, 2, 3, 4 }; 
var words = new [] { "one", "two", "three", "four" }; 

var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w }); 
foreach(var nw in numbersAndWords) 
{ 
    Console.WriteLine(nw.Number + nw.Word); 
} 

नामित क्षेत्रों के साथ गुमनाम प्रकार के लिए एक विकल्प है, तो आप भी एक टपल और उसके स्थिर Tuple.Create सहायक का उपयोग करके ब्रेसिज़ पर बचा सकता है के रूप में:

foreach (var nw in numbers.Zip(words, Tuple.Create)) 
{ 
    Console.WriteLine(nw.Item1 + nw.Item2); 
} 
+2

से बेहतर दिखता है यहां पर एक लेख है: http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part- 3-इंटरमेज़ो-लिनक-एस-न्यू-ज़िप-ऑपरेटर.एएसपी –

+1

उन ज़िप ऑपरेशंस के बारे में कुछ भी नहीं पता था, मैं उस विषय पर एक छोटा सा शोध कर दूंगा। धन्यवाद! – Hugo

+3

@ ह्यूगो: यह कार्यात्मक प्रोग्रामिंग में एक मानक निर्माण है :) –

-1

मैं समझता हूँ/उम्मीद है कि सूचियों की लंबाई समान है: नहीं, आपकी एकमात्र शर्त लूप के लिए एक पुराने पुराने मानक के साथ जा रही है।

0

नहीं, आपको इसके लिए फॉर-लूप का उपयोग करना होगा।

for (int i = 0; i < lst1.Count; i++) 
{ 
    //lst1[i]... 
    //lst2[i]... 
} 

आप ऐसा नहीं कर सकते जैसे

foreach (var objCurrent1 int lst1, var objCurrent2 in lst2) 
{ 
    //... 
} 
+0

क्या होगा यदि उनके पास अलग-अलग मायने रखती हैं? –

+0

फिर एक प्रस्ताव जो संख्याओं की मनमाने ढंग से सूची स्वीकार करेगा, वह भी काम नहीं करेगा, इस प्रकार पूरी चीज बेकार हो जाएगी। –

10

आप संघ या Concat उपयोग कर सकते हैं, पूर्व डुप्लिकेट निकाल देता है, बाद में

foreach (var item in List1.Union(List1)) 
{ 
    //TODO: Real code goes here 
} 

foreach (var item in List1.Concat(List1)) 
{ 
    //TODO: Real code goes here 
} 
+0

यह काम नहीं करेगा अगर वे विभिन्न प्रकार की सूचियां हैं। –

+0

संघ का उपयोग करने में एक और समस्या यह है कि यदि वे बराबर के रूप में मूल्यांकन करते हैं तो यह उदाहरण निकाल सकता है। यह हमेशा आप जो चाहते हैं वह नहीं हो सकता है। –

+1

मुझे लगता है कि उनका इरादा उसी प्रकार के संग्रह, – albertein

3

नहीं है यहाँ एक कस्टम IEnumerable < है कुछ > एक्सटेंशन विधि जिसका उपयोग एक साथ दो सूचियों के माध्यम से लूप करने के लिए किया जा सकता है।

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

namespace ConsoleApplication1 
{ 
    public static class LinqCombinedSort 
    { 
     public static void Test() 
     { 
      var a = new[] {'a', 'b', 'c', 'd', 'e', 'f'}; 
      var b = new[] {3, 2, 1, 6, 5, 4}; 

      var sorted = from ab in a.Combine(b) 
         orderby ab.Second 
         select ab.First; 

      foreach(char c in sorted) 
      { 
       Console.WriteLine(c); 
      } 
     } 

     public static IEnumerable<Pair<TFirst, TSecond>> Combine<TFirst, TSecond>(this IEnumerable<TFirst> s1, IEnumerable<TSecond> s2) 
     { 
      using (var e1 = s1.GetEnumerator()) 
      using (var e2 = s2.GetEnumerator()) 
      { 
       while (e1.MoveNext() && e2.MoveNext()) 
       { 
        yield return new Pair<TFirst, TSecond>(e1.Current, e2.Current); 
       } 
      } 

     } 


    } 
    public class Pair<TFirst, TSecond> 
    { 
     private readonly TFirst _first; 
     private readonly TSecond _second; 
     private int _hashCode; 

     public Pair(TFirst first, TSecond second) 
     { 
      _first = first; 
      _second = second; 
     } 

     public TFirst First 
     { 
      get 
      { 
       return _first; 
      } 
     } 

     public TSecond Second 
     { 
      get 
      { 
       return _second; 
      } 
     } 

     public override int GetHashCode() 
     { 
      if (_hashCode == 0) 
      { 
       _hashCode = (ReferenceEquals(_first, null) ? 213 : _first.GetHashCode())*37 + 
          (ReferenceEquals(_second, null) ? 213 : _second.GetHashCode()); 
      } 
      return _hashCode; 
     } 

     public override bool Equals(object obj) 
     { 
      var other = obj as Pair<TFirst, TSecond>; 
      if (other == null) 
      { 
       return false; 
      } 
      return Equals(_first, other._first) && Equals(_second, other._second); 
     } 
    } 

} 
0

आप इसी से एक के साथ एक तत्व तुम कर सकते हो

Enumerable.Range(0, List1.Count).All(x => List1[x] == List2[x]); 

यही सच वापस आ जाएगी, तो हर आइटम दूसरी सूची

पर इसी के बराबर है चाहते हैं कि लगभग है, तो लेकिन यदि आप अधिक विस्तारित करते हैं तो यह काफी नहीं है जो आप चाहते हैं।

0

यह विधि एक सूची कार्यान्वयन के लिए काम करेगी और इसे एक विस्तार विधि के रूप में कार्यान्वित किया जा सकता है।

public void TestMethod() 
{ 
    var first = new List<int> {1, 2, 3, 4, 5}; 
    var second = new List<string> {"One", "Two", "Three", "Four", "Five"}; 

    foreach(var value in this.Zip(first, second, (x, y) => new {Number = x, Text = y})) 
    { 
     Console.WriteLine("{0} - {1}",value.Number, value.Text); 
    } 
} 

public IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(List<TFirst> first, List<TSecond> second, Func<TFirst, TSecond, TResult> selector) 
{ 
    if (first.Count != second.Count) 
     throw new Exception(); 

    for(var i = 0; i < first.Count; i++) 
    { 
     yield return selector.Invoke(first[i], second[i]); 
    } 
} 
13

यदि आप .NET 4.0 के लिए प्रतीक्षा नहीं करना चाहते हैं, तो आप अपनी ज़िप विधि को कार्यान्वित कर सकते हैं। निम्नलिखित .NET 2.0 के साथ काम करता है। आप कार्यान्वयन को समायोजित कर सकते हैं कि आप इस मामले को कैसे संभालना चाहते हैं, जहां दो गणनाएं (या सूचियों) की अलग-अलग लंबाई होती है: यह एक लंबी गणना के अंत तक जारी रहता है, जो छोटी गणना से गुम वस्तुओं के लिए डिफ़ॉल्ट मान लौटाता है।

static IEnumerable<KeyValuePair<T, U>> Zip<T, U>(IEnumerable<T> first, IEnumerable<U> second) 
    { 
     IEnumerator<T> firstEnumerator = first.GetEnumerator(); 
     IEnumerator<U> secondEnumerator = second.GetEnumerator(); 

     while (firstEnumerator.MoveNext()) 
     { 
      if (secondEnumerator.MoveNext()) 
      { 
       yield return new KeyValuePair<T, U>(firstEnumerator.Current, secondEnumerator.Current); 
      } 
      else 
      { 
       yield return new KeyValuePair<T, U>(firstEnumerator.Current, default(U)); 
      } 
     } 
     while (secondEnumerator.MoveNext()) 
     { 
      yield return new KeyValuePair<T, U>(default(T), secondEnumerator.Current); 
     } 
    } 

    static void Test() 
    { 
     IList<string> names = new string[] { "one", "two", "three" }; 
     IList<int> ids = new int[] { 1, 2, 3, 4 }; 

     foreach (KeyValuePair<string, int> keyValuePair in ParallelEnumerate(names, ids)) 
     { 
      Console.WriteLine(keyValuePair.Key ?? "<null>" + " - " + keyValuePair.Value.ToString()); 
     } 
    } 
+1

अच्छी विधि! :)। आप .NET 4 ज़िप विधि http://msdn.microsoft.com/en-us/library/dd267698.aspx के समान हस्ताक्षर का उपयोग करने के लिए कुछ समायोजन कर सकते हैं और एक केवीपी के बजाय परिणाम चयनकर्ता (पहला, दूसरा) वापस कर सकते हैं। –

+0

ध्यान दें कि यह विधि अपने एन्युमरेटर्स का निपटान नहीं करती है जो एक समस्या बन सकती है, उदा। अगर इसे खुली फाइलों की लाइनों पर संख्याओं के साथ प्रयोग किया जाता है। – Lii

1

तुम भी बस एक स्थानीय पूर्णांक चर इस्तेमाल कर सकते हैं, तो सूचियों में एक ही लंबाई है: सी # 7, आप tuples उपयोग कर सकते हैं

List<classA> listA = fillListA(); 
List<classB> listB = fillListB(); 

var i = 0; 
foreach(var itemA in listA) 
{ 
    Console.WriteLine(itemA + listB[i++]); 
} 
0

के बाद से ...

int[] nums = { 1, 2, 3, 4 }; 
string[] words = { "one", "two", "three", "four" }; 

foreach (var tuple in nums.Zip(words, (x, y) => (x, y))) 
{ 
    Console.WriteLine($"{tuple.Item1}: {tuple.Item2}"); 
} 

// or... 
foreach (var tuple in nums.Zip(words, (x, y) => (Num: x, Word: y))) 
{ 
    Console.WriteLine($"{tuple.Num}: {tuple.Word}"); 
} 
संबंधित मुद्दे