C # .NET में दो (या अधिक) सूचियों को एक में मिलाएं


246

क्या .NET # का उपयोग करके दो या अधिक सूचियों को एक ही सूची में बदलना संभव है?

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

public static List<Product> GetAllProducts(int categoryId){ .... }
.
.
.
var productCollection1 = GetAllProducts(CategoryId1);
var productCollection2 = GetAllProducts(CategoryId2);
var productCollection3 = GetAllProducts(CategoryId3);

क्या आप ProductCollection1 2 और 3 को मर्ज करना चाहते हैं?

क्या आपका मतलब एक सूची में एक से अधिक सूची में विलय करना है?
अमृ बदावी

आपका उदाहरण मुझे भ्रमित कर रहा है ... क्या आप AddRangeमैथोड की तलाश कर रहे हैं ?
बॉबी

जवाबों:


457

आप LINQ Concatऔर ToListविधियों का उपयोग कर सकते हैं :

var allProducts = productCollection1.Concat(productCollection2)
                                    .Concat(productCollection3)
                                    .ToList();

ध्यान दें कि ऐसा करने के लिए और अधिक कुशल तरीके हैं - ऊपर मूल रूप से सभी प्रविष्टियों के माध्यम से लूप होगा, एक गतिशील आकार के बफर का निर्माण करेगा। जैसा कि आप शुरू करने के लिए आकार की भविष्यवाणी कर सकते हैं, आपको इस गतिशील आकार की आवश्यकता नहीं है ... इसलिए आप इसका उपयोग कर सकते हैं:

var allProducts = new List<Product>(productCollection1.Count +
                                    productCollection2.Count +
                                    productCollection3.Count);
allProducts.AddRange(productCollection1);
allProducts.AddRange(productCollection2);
allProducts.AddRange(productCollection3);

( दक्षता के AddRangeलिए विशेष आवरण है ICollection<T>।)

मैं इस दृष्टिकोण को तब तक नहीं ले सकता जब तक कि आपको वास्तव में नहीं करना है।


4
BTW, productCollection1.ForEach(p => allProducts.Add(p))AddRange की तुलना में अधिक प्रदर्शनशील है।
मार्क क्लेमेंट

8
@MarcCliment: यह एक काफी बोल्ड कंबल बयान है - विशेष रूप AddRangeसे जैसा कि एक अंतर्निहित सरणी से दूसरे में एक ब्लॉक कॉपी करने के लिए मिलता है। क्या आपके पास इसके सबूत के लिए कोई लिंक है?
जॉन स्कीट

4
@MarcCliment: अच्छी तरह से एक चीज के लिए, आपके परीक्षणों में आप सही अंतिम आकार के साथ सूची नहीं बना रहे हैं - जबकि मेरे उत्तर में कोड है। ऐसा करें, और AddRange का उपयोग करके 10000 * 10000 परीक्षण तेज है, कम से कम - हालांकि अन्य परिणाम असंगत हैं। (आपको परीक्षणों के बीच कचरा संग्रह को भी मजबूर करना चाहिए - और मैं तर्क दूंगा कि बहुत ही छोटे परीक्षण अर्थहीन रूप से छोटे हैं।)
जॉन स्कीट

6
@MarcCliment: कौन सा विशेष मामला? कौन सी सीएलआर? कौन सा CPU आर्किटेक्चर? मेरी मशीन पर मुझे परिणामों का मिश्रण मिलता है। यही कारण है कि मैं "बीटीडब्ल्यू, productionCollection1.ForEach(...)AddRange की तुलना में अधिक प्रदर्शनशील " जैसे कंबल स्टेटमेंट को स्वीकार / स्वीकार करने के लिए तैयार हूं । परफॉर्मेंस बहुत कम ही इतनी आसानी से वर्णित है। मैं कर रहा हूँ आश्चर्य है कि AddRange यह handily हालांकि पिटाई नहीं है - मैं जांच करने के लिए है कि आगे की जरूरत है।
जॉन स्कीट

15
मैंने gist ( gist.github.com/mcliment/4690433 ) को बेंचमार्कडॉटनेट का उपयोग करते हुए प्रदर्शन परीक्षण के साथ अद्यतन किया है और ठीक से परीक्षण किया है, AddRangeयह कच्ची गति के लिए सबसे अच्छा विकल्प है (लगभग 4x और जितनी बड़ी सूची उतनी बेहतर वृद्धि, जॉन के रूप में। suggeste।
मार्क क्लाइम्ट डिक

41

मान लें कि आप निर्दिष्ट श्रेणी-Ids के लिए सभी उत्पादों से युक्त एक सूची चाहते हैं , तो आप अपनी क्वेरी को एक समतल संचालन के बाद के प्रक्षेपण के रूप में मान सकते हैं । एक LINQ ऑपरेटर है जो ऐसा करता है :।SelectMany

// implicitly List<Product>
var products = new[] { CategoryId1, CategoryId2, CategoryId3 }
                     .SelectMany(id => GetAllProducts(id))
                     .ToList();

C # 4 में, आप SelectMany को छोटा कर सकते हैं: .SelectMany(GetAllProducts)

यदि आपके पास पहले से ही प्रत्येक ईद के लिए उत्पादों का प्रतिनिधित्व करने वाली सूचियाँ हैं, तो आपको जो चाहिए वह एक अवकास है , जैसा कि अन्य लोग बताते हैं।


8
यदि ओपी को किसी अन्य कारण से अलग-अलग सूचियों की आवश्यकता नहीं है, तो यह एक महान समाधान है।
जॉन स्कीट

2
इसी तरह की समस्या होने और एक प्रश्न छोड़ना और पोस्ट करना था, जब मैंने यह पाया। यह सबसे अच्छा जवाब है। खासकर अगर कोड में पहले से ही एक सूची या सरणी में उन श्रेणियां हैं, जो मेरे मामले में सच थी।

22

आप उन्हें LINQ का उपयोग करके जोड़ सकते हैं:

  list = list1.Concat(list2).Concat(list3).ToList();

उपयोग करने का अधिक पारंपरिक दृष्टिकोण List.AddRange()हालांकि अधिक कुशल हो सकता है।





4

मुझे पता है कि यह एक पुराना सवाल है मुझे लगा कि मैं अपने 2 सेंट जोड़ सकता हूं।

यदि आप एक है List<Something>[]आप का उपयोग कर उन्हें शामिल कर सकते हैंAggregate

public List<TType> Concat<TType>(params List<TType>[] lists)
{
    var result = lists.Aggregate(new List<TType>(), (x, y) => x.Concat(y).ToList());

    return result;
}

उम्मीद है की यह मदद करेगा।


2

मैंने पहले ही टिप्पणी कर दी है, लेकिन मुझे लगता है कि यह एक वैध विकल्प है, बस परीक्षण करें कि क्या आपके वातावरण में बेहतर एक समाधान या दूसरा है। मेरे विशेष मामले में, source.ForEach(p => dest.Add(p))क्लासिक की तुलना में बेहतर प्रदर्शन करता है , AddRangeलेकिन मैंने जांच नहीं की है कि निम्न स्तर पर क्यों।

आप यहां एक उदाहरण कोड देख सकते हैं: https://gist.github.com/mcliment/4690433

तो विकल्प होगा:

var allProducts = new List<Product>(productCollection1.Count +
                                    productCollection2.Count +
                                    productCollection3.Count);

productCollection1.ForEach(p => allProducts.Add(p));
productCollection2.ForEach(p => allProducts.Add(p));
productCollection3.ForEach(p => allProducts.Add(p));

यह देखने के लिए परीक्षण करें कि क्या यह आपके लिए काम करता है।

डिस्क्लेमर : मैं इस समाधान की वकालत नहीं कर रहा हूं, मुझे Concatसबसे स्पष्ट लगता है। मैंने सिर्फ जॉन के साथ अपनी चर्चा में कहा- कि मेरी मशीन में यह मामला इससे बेहतर प्रदर्शन करता है AddRange, लेकिन वह कहते हैं, मेरे मुकाबले कहीं अधिक ज्ञान के साथ, कि इसका कोई मतलब नहीं है। अगर आप तुलना करना चाहते हैं तो जिस्ट है।


टिप्पणियों में जॉन स्कीट के साथ आपकी बहस के बावजूद, मैं उनके प्रस्तावित समाधान द्वारा पेश की गई सफाई को पसंद करता हूं, यह सिर्फ कोड की मंशा के अनुसार अनावश्यक व्याख्या जोड़ता है।
विक्स

1
मुझे लगता है कि सबसे स्पष्ट विकल्प कॉनैट है AddRange के सामान्यीकरण के रूप में, शब्दार्थ रूप से अधिक सही है और सूची को उस स्थान में संशोधित नहीं करता है जो इसे चेनेबल बनाता है। जॉन के साथ चर्चा प्रदर्शन के बारे में थी, न कि स्वच्छता के बारे में।
मार्क क्लेमेंट जूल

मेरे पास कुछ इस तरह है: var allProducts = lstName.Concat(lstCMSID) .Concat(lstSpecialtyPhys) .ToList();जो इसे ग्रिड व्यू में जोड़ता है लेकिन एक कॉलम के रूप में। मैं उन्हें तीन अलग-अलग स्तंभों में विभाजित करना चाहूंगा।
Si8

2
// I would make it a little bit more simple

 var products = new List<List<product>> {item1, item2, item3 }.SelectMany(id => id).ToList();

इस तरह यह एक बहुआयामी सूची है और .SelectMany () इसे उत्पाद के IEnumerable में समतल कर देगा फिर मैं .ToList () विधि का उपयोग करता हूं।


2

किसी एक सूची में सूचियों को मर्ज या संयोजित करना।

  • एक बात है जो सच होनी चाहिए: दोनों सूची का प्रकार समान होगा।

  • उदाहरण के लिए : यदि हमारे पास सूची है stringतो हम मौजूदा सूची में एक और सूची जोड़ सकते हैं जिसमें टाइप स्ट्रिंग की सूची है अन्यथा हम नहीं कर सकते।

उदाहरण :

class Program
{
   static void Main(string[] args)
   {
      List<string> CustomerList_One = new List<string> 
      {
         "James",
         "Scott",
         "Mark",
         "John",
         "Sara",
         "Mary",
         "William",
         "Broad",
         "Ben",
         "Rich",
         "Hack",
         "Bob"
      };

      List<string> CustomerList_Two = new List<string> 
      {
         "Perter",
         "Parker",
         "Bond",
         "been",
         "Bilbo",
         "Cooper"
      };

      // Adding all contents of CustomerList_Two to CustomerList_One.
      CustomerList_One.AddRange(CustomerList_Two);

      // Creating another Listlist and assigning all Contents of CustomerList_One.
      List<string> AllCustomers = new List<string>();

      foreach (var item in CustomerList_One)
      {
         AllCustomers.Add(item);
      }

      // Removing CustomerList_One & CustomerList_Two.
      CustomerList_One = null;

      CustomerList_Two = null;
      // CustomerList_One & CustomerList_Two -- (Garbage Collected)
      GC.Collect();

      Console.WriteLine("Total No. of Customers : " +  AllCustomers.Count());
      Console.WriteLine("-------------------------------------------------");
      foreach (var customer in AllCustomers)
      {
         Console.WriteLine("Customer : " + customer);
      }
      Console.WriteLine("-------------------------------------------------");

   }
}

1

विशेष मामले में: "सूची 1 के सभी तत्व एक नई सूची 2 में जाते हैं": (जैसे एक स्ट्रिंग सूची)

List<string> list2 = new List<string>(list1);

इस स्थिति में, list2 से सभी तत्वों के साथ list2 उत्पन्न होता है।



0

जब आपको कुछ सूची मिली, लेकिन आप नहीं जानते कि वास्तव में कितने हैं, तो इसका उपयोग करें:

listsOfProducts वस्तुओं से भरी कुछ सूचियाँ शामिल हैं।

List<Product> productListMerged = new List<Product>();

listsOfProducts.ForEach(q => q.ForEach(e => productListMerged.Add(e)));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.