2012-04-24 13 views
19

मेरे पास तीन हैं (3-4 से अधिक जेनेरिक सूची होना संभव है, लेकिन इस उदाहरण में 3) जेनेरिक सूचियां।सी # ज़िप में दो से अधिक जेनेरिक सूचियों को कैसे गठबंधन करें?

List<string> list1 

List<string> list2 

List<string> list3 

सभी सूचियों में तत्वों (समान गणना) की संख्या समान है। तीन के लिए पिन के साथ simmilary का उपयोग कैसे करें

var result = list1.Zip(list2, (a, b) => new { 
    test1 = f, 
    test2 = b 
} 

मैं प्रयोग किया जाता है कि foreach बयान के लिए, foreach प्रत्येक सूची से बचने के लिए,

foreach(var item in result){ 
Console.WriteLine(item.test1 + " " + item.test2); 
} 

की तरह:

मुझे लगता है कि ज़िप के साथ दो सूचियों के संयोजन के लिए इस्तेमाल किया सूचियां?

धन्यवाद

संपादित करें:

मुझे पसंद हैं:

List<string> list1 = new List<string>{"test", "otherTest"}; 

List<string> list2 = new List<string>{"item", "otherItem"}; 

List<string> list3 = new List<string>{"value", "otherValue"}; 
ज़िप बाद

(मैं विधि पता नहीं है) VS2010 डिबग मोड में, मैं परिणाम चाहते हैं ()

[0] { a = {"test"}, 
     b = {"item"}, 
     c = {"value"} 
    } 

[1] { a = {"otherTest"}, 
     b = {"otherItem"}, 
     c = {"otherValue"} 
    } 

यह कैसे करें?

+0

संभावित डुप्लिकेट [लिंक का उपयोग करके 3 संग्रहों से आइटम बनाएं] (http://stackoverflow.com/questions/5284315/create-items-from-3-collections-using-linq) – ensisNoctis

उत्तर

16

मेरे लिए सबसे स्पष्ट तरीका Zip दो बार उपयोग करना होगा।

उदाहरण के लिए,

var results = l1.Zip(l2, (x, y) => x + y).Zip(l3, (x, y) => x + y); 

गठबंधन (जोड़ें) तीन List<int> वस्तुओं के तत्वों होगा।

अद्यतन:

तुम इतनी तरह, एक नया विस्तार विधि है कि तीन IEnumerable रों के साथ एक Zip तरह कार्य करता है निर्धारित कर सकते हैं:

public static class MyFunkyExtensions 
{ 
    public static IEnumerable<TResult> ZipThree<T1, T2, T3, TResult>(
     this IEnumerable<T1> source, 
     IEnumerable<T2> second, 
     IEnumerable<T3> third, 
     Func<T1, T2, T3, TResult> func) 
    { 
     using (var e1 = source.GetEnumerator()) 
     using (var e2 = second.GetEnumerator()) 
     using (var e3 = third.GetEnumerator()) 
     { 
      while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) 
       yield return func(e1.Current, e2.Current, e3.Current); 
     } 
    } 
} 

उपयोग (उसी संदर्भ में के रूप में ऊपर) अब बन जाता है:

var results = l1.ZipThree(l2, l3, (x, y, z) => x + y + z); 

इसी प्रकार, आप तीन सूचियों को अब संयुक्त कर सकते हैं:

var results = list1.ZipThree(list2, list3, (a, b, c) => new { a, b, c }); 
+0

ऐसा करने का यह एक अच्छा तरीका है (x, y) चर के साथ क्योंकि मैं 'foreach' कथन के लिए उपयोग करना चाहता हूं और प्रत्येक तत्व से मान प्राप्त करना –

+0

क्या आप संपादित पोस्ट पर एक नज़र डाल सकते हैं? धन्यवाद –

+0

मैंने अपना जवाब अपडेट किया है; मुझे आशा है कि यह वही करता है जो आपको चाहिए। – GolfWolf

2
class Program 
{ 
    static void Main(string[] args) 
    { 
     List<string> list1 = new List<string> { "test", "otherTest" }; 
     List<string> list2 = new List<string> { "item", "otherItem" }; 
     List<string> list3 = new List<string> { "value", "otherValue" }; 

     var result = CombineListsByLayers(list1, list2, list3); 
    } 

    public static List<string>[] CombineListsByLayers(params List<string>[] sourceLists) 
    { 
     var results = new List<string>[sourceLists[0].Count]; 

     for (var i = 0; i < results.Length; i++) 
     { 
      results[i] = new List<string>(); 
      foreach (var sourceList in sourceLists) 
       results[i].Add(sourceList[i]); 
     } 
     return results; 
    } 
+0

कभी-कभी एक सिगार बस एक सिगार रहना चाहिए। –

+0

मैंने अन्य उत्तरों को पढ़ा जो आपके प्रश्न के बेहतर उत्तर हैं। लेकिन ईमानदारी से, कुछ ऐसा क्यों है जो इतना पढ़ा जा सकता है और लिखने के लिए x10 गुना अधिक लेता है? –

+0

जब मैं सही तरीके से प्रश्न पढ़ता हूं तो यह मदद करता है :), मेरे द्वारा +1। – Phil

2

आप झरना ज़िप तरीकों और गुमनाम वर्गों और टपल परिणाम के साथ सी # में कई सूचियां संयोजित कर सकते हैं।

List<string> list1 = new List<string> { "test", "otherTest" }; 
List<string> list2 = new List<string> { "item", "otherItem" }; 
List<string> list3 = new List<string> { "value", "otherValue" }; 

IEnumerable<Tuple<string, string, string>> result = list1 
    .Zip(list2, (e1, e2) => new {e1, e2}) 
    .Zip(list3, (z1, e3) => Tuple.Create(z1.e1, z1.e2, e3)); 

परिणाम है:

[0] 
{(test, item, value)} 
    Item1: "test" 
    Item2: "item" 
    Item3: "value" 
+2

एक साइड-नोट पर: [Tuple.Create] का उपयोग करना आसान है (https://msdn.microsoft.com/en-us/library/dd383822 (v = vs.110) .aspx), तो आप नहीं करते जेनेरिक पैरामीटर निर्दिष्ट करना होगा। – Maarten

2

एक और काफी रोचक समाधान है कि मैं के बारे में पता कर रहा हूँ है।यह ज्यादातर शैक्षणिक परिप्रेक्ष्य से दिलचस्प है, लेकिन अगर किसी को सूची की अलग-अलग गणनाओं को ज़ोट करने की ज़रूरत है, तो यह भी उपयोगी हो सकता है।

यह विधि .NET के LINQ SelectMany फ़ंक्शन को ओवरराइड करता है जब आप LINQ के क्वेरी सिंटैक्स का उपयोग करते समय एक सम्मेलन द्वारा लिया जाता है। मानक SelectMany कार्यान्वयन एक कार्टेसियन उत्पाद करता है। ओवरराइड एक इसके बजाय ज़िप कर सकता है। वास्तविक क्रियान्वयन हो सकता है:

static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, 
     Func<TSource, IEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> select) 
{ 
    using (var e1 = source.GetEnumerator()) 
     using (var e2 = selector(default(TSource)).GetEnumerator()) 
      while (true) 
       if (e1.MoveNext() && e2.MoveNext()) 
        yield return select(e1.Current, e2.Current); 
       else 
        yield break; 
} 

यह थोड़ा डरावना लग रहा है लेकिन यह जो करता है, तो एक बार लिखा है, कई स्थानों में इस्तेमाल किया जा सकता ज़िप करना का एक तर्क है और ग्राहक के कोड बहुत अच्छे लग रहे हैं - आप के किसी भी संख्या को ज़िप कर सकते हैं IEnumerable<T> मानक LINQ क्वेरी सिंटैक्स का उपयोग:

var titles = new string[] { "Analyst", "Consultant", "Supervisor"}; 
var names = new string[] { "Adam", "Eve", "Michelle" }; 
var surnames = new string[] { "First", "Second", "Third" }; 

var results = 
    from title in titles 
    from name in names 
    from surname in surnames 
    select $"{ title } { name } { surname }"; 

आप तो निष्पादित हैं:

foreach (var result in results) 
    Console.WriteLine(result); 

आप मिल जाएगा:

Analyst Adam First 
Consultant Eve Second 
Supervisor Michelle Third 

आपको इस कक्षा को अपनी कक्षा में निजी रखना चाहिए क्योंकि अन्यथा आप मूल रूप से आसपास के कोड के व्यवहार को बदल देंगे। साथ ही, एक नया प्रकार उपयोगी होगा ताकि यह IENumerables के लिए मानक LINQ व्यवहार के साथ सहयोग नहीं करेगा।

मैं इस विस्तार विधि + कुछ लाभ के साथ एक बार एक छोटे से ग # परियोजना बना लिया है शैक्षिक उद्देश्यों के लिए: https://github.com/lukiasz/Zippable

इसके अलावा, आप इस दिलचस्प पाते हैं, मैं दृढ़ता से Jon Skeet's Reimplementing LINQ to Objects articles सलाह देते हैं।

मज़े करो!

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