2009-07-26 18 views
27

अब मैं अपने सभी डेटा को कैश (ऑब्जेक्ट्स) में एक सूची के रूप में प्राप्त करने के लिए एक मंच आया हूं और मेरी अगली चीज़ मुझे सूची से कुछ उदाहरणों को निकालना है।LINQ या Lambda का उपयोग करके किसी सूची से उदाहरण निकालें?

आम तौर पर, मैं इस तरह हटाने के करते हैं:

List<T> list; 
List<T2> toBeRemovedItems; 
// populate two lists 
foreach(T2 item in toBeRemovedItems) 
{ 
    list.Remove(delegate(T one) { 
     // build a condition based on item 
     // return true or false 
    }); 
} 

अधिक विशिष्ट होना करने के लिए, मैं वास्तव में तैयार करते हैं या गतिशील वर्ग (नहीं एक औपचारिक परिभाषित वर्ग) के toBeRemvoedItems सूची को पॉप्युलेट। उदाहरण के लिए, टी वर्ग MyClass और दूर करने के लिए कोड की तरह कुछ है:

class MyClass<C> { 
    public string Value1 { get; set; } 
    public int Value2 { get; set; } 
    public C ObjectC { get; set; } 
} 
.... 
List<MyClass<C>> list; 
// populate list 
// populate toBeRemovedItems. Here is an example of hard-coded codes: 
var toBeRemovedLItems = new[] { 
    new { Value1="a", Value2 = 1}, 
    new { Value2="x", Value2 = 10}, 
    ... 
}; 
// toBeRemovedItems may be the result of Select from a collection 
foreach(var item in toBeRemovedLItems) 
{ 
    list.Remove(delegate(MyClass one) { 
     return one.Value1 = item.Value1 && one.Value2 < item.Value2; 
    }); 
} 

मैं MSDN से IEnumerable इंटरफ़ेस में Remove() विधि के लिए खोज करने की कोशिश की, लेकिन मैं वहाँ Remove() की विधि नहीं मिल सकता है (यह समझ में आता है कि IEnumerable सिर्फ गणना के लिए प्रयोग किया जाता है)। सूची वर्ग में, Remove(...) विधियों को कई अधिभारित किया गया है। मुझे यकीन नहीं है कि क्या LINQ या Lambda अभिव्यक्तियों का उपयोग कर सूची से आइटम्स को निकालने का कोई वैकल्पिक तरीका है?

वैसे, मैंने एक सूची के खिलाफ एक क्वेरी करने के लिए एक प्रश्न के बारे में सोचा था या एक नई IEnumerable सूची जहां एक सूची से चलती वस्तुओं के समान स्थितियां हैं। हालांकि, मैं अपनी कैश की गई सूची से वस्तुओं को हटाना पसंद करता हूं, और कुछ मामलों में मैं कक्षा में सूची संपत्ति को किसी नई सूची (उदाहरण के लिए निजी सेट) में रीसेट नहीं कर सकता।

MyClass one; //initialize MyClass 
list.RemoveAll(item => one.Value1 == item.Value1 && one.Value2 < item.Value2); 
+0

डुप्ली की तरह दिखता है। खैर, मूल रूप से आपने पोस्ट में सभी संभावित तरीकों का उल्लेख किया है ... http://stackoverflow.com/questions/1120336/what-is-the-easiest-way-to-foreach-through-a-listt-removing-unwanted -objects –

उत्तर

40

आप विधि RemoveAll इस्तेमाल कर सकते हैं। ओह अच्छा।

+7

मुझे लगता है कि यह वास्तव में सूची की एक विधि है, विस्तार विधि – Jimmy

+0

धन्यवाद नहीं! मैं अपनी पोस्ट अपडेट करता हूं। –

+0

मेरी समझ यह है कि आप एक समय में एक आइटम हटाते हैं। फिर भी मुझे प्रत्येक को रचर्ड हेन के सुझाव की तरह लूप करना है। –

2
foreach(var item in toBeRemovedLItems) { 
    list.RemoveAll(one => one.Value1 == item.Value1 && one.Value2 < item.Value2); 
} 

बहुत देर हो गई फिर से:

+0

फ़ोरैच लूप के बिना, toBeRemovedItems को निकालने के लिए RemoveAll (lambda func) को दो पैरामीटर पास करना संभव है, तो सुनिश्चित नहीं है। निश्चित रूप से यह पहले से ही बहुत पठनीय है। –

21

आप LINQ की कहां विधि का उपयोग उन मानों को फ़िल्टर करने के लिए कर सकते हैं जो सूची का हिस्सा नहीं होना चाहिए। परिणाम हटाए गए तत्वों के साथ IEnumerable<T> है।

var res = list.Where(item => !(one.Value1 == item.Value1 && one.Value2 < item.Value2)); 

यह मूल List<T> उदाहरण अद्यतन नहीं होगा, लेकिन इसके बजाय एक नया IEnumerable<T> हटाया मूल्यों के साथ पैदा करेगा।

+0

परफ क्या है। वस्तुओं को हटाने के लिए लूप के लिए यह बनाम बनाम हिट करें? –

4

मैं कुछ वस्तुओं को छान के जारेड के सुझाव से सहमत है, लेकिन यह Value1 पर एक join की तरह दिखता है एक अधिक कुशल दृष्टिकोण होगा:

var res = from item1 in list 
      join item2 in toBeRemovedList 
      on item1.Value1 equals item2.Value1 
      where item1.Value2 >= item2.Value2 
      select item1; 

अद्यतन: जाहिर है मैं पढ़ना शामिल असफल - नया दृष्टिकोण :

var removeDict = toBeRemovedList.ToDictionary(i => i.Value1, i => i.Value2); 
list.RemoveAll(item => { 
    int itemToRemoveValue2; 
    if(removeDict.TryGetValue(item.Value1, out itemToRemoveValue2)) 
     return item.Value2 < itemToRemoveValue2; 
    return false; 
}); 

बेशक, यदि आपकी सूची को निकालने के लिए एक शब्दकोश के रूप में शुरू किया जा सकता है तो यह बेहतर होगा। आखिरकार, हम अपने मैच को Value1 पर अधिक कुशल बनाने की कोशिश कर रहे हैं।

+0

एसक्यूएल इंटरसेक्ट के समान ही शामिल है? या इस तरह की LINQ क्वेरी? –

+0

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

+0

नोट किया गया - उत्तर अपडेट किया गया। – dahlbyk

5

यदि मुझे दो सूची से एक अद्वितीय सेट तैयार करने के लिए सही प्रश्न मिलता है।

इस के लिए, आप निम्नलिखित

सूची List1 उपयोग कर सकते हैं; सूची सूची 2;

सूची सूची 3 = सूची 1।छोड़कर (list2)

सूची 3 में अद्वितीय आइटम होंगे।

+0

यह पहला जवाब है जो मेरे लक्ष्य को संबोधित करता है, जो लैम्ब्डा से मेल खाने वाली वस्तुओं की गणना को निकालने और प्राप्त करने के लिए होता है। –

+0

इस काम के लिए एक ही तरह का संग्रह होना चाहिए, हालांकि। – vapcguy

1

संग्रहों के लिए जो सूची नहीं हैं (RemoveAll का पर्दाफाश नहीं कर सकते हैं), आप अभी भी एक-लाइनर के साथ आइटम हटा सकते हैं।

इनलाइन को प्रतिस्थापित करने के लिए, बस निकालने के लिए आइटम्स की एक सूची जेनरेट करें, फिर उसके माध्यम से चलाएं और निकालें कोड निष्पादित करें।

var dictionary = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}}; 
dictionary 
    .Where(where_item => 
     ((where_item.Key == "foo") && (where_item.Value == "0")) 
     || ((where_item.Key == "boo") && (where_item.Value == "1")) 
    ) 
    .ToList() 
    .ForEach(remove_item => { 
     dictionary.Remove(remove_item.Key); 
    }); 

प्रतिलिपि में प्रतिस्थापित करने के लिए, बस एक फ़िल्टर किए गए गणित उत्पन्न करें और एक नई प्रतिलिपि वापस करें।

var dictionary0 = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}}; 
var dictionary1 = dictionary0 
    .Where(where_item => 
     ((where_item.Key == "foo") && (where_item.Value == "0")) 
     || ((where_item.Key == "boo") && (where_item.Value == "1")) 
    ) 
    .ToDictionary(each_item => each_item.Key, each_item => each_item.Value); 
0

शायद आप ऐसा कुछ करने की कोशिश कर रहे हैं?

List<T> firstList; 
List<T2> toBeRemovedItems; 
List<T> finalList; 

foreach(T item in firstList) 
{ 
    toBeRemovedItems = CheckIfWeRemoveThisOne(item.Number, item.Id); 
    if (toBeRemovedItems == null && toBeRemovedItems.Count() == 0) 
     finalList.Add(item); 
} 

इस तरह मैं एक List<ViewModel> और एक List<Model> के बीच डुप्लिकेट से छुटकारा पाने के साथ किसी समस्या का समाधान करने में कामयाब रहे है। मैंने फ़ंक्शन का उपयोग यह जांचने के लिए किया था कि item.Number परिभाषित विशेषता के रूप में आईडी का उपयोग करके किसी अन्य आइटम से संबंधित है या नहीं। अगर इसे मूल सूची (जिसे मैं List<Model> वापस प्राप्त कर रहा था, इसे वापस लेने और निकालने के बजाय इसे एक और आइटम (डुप्लिकेट) मिला, और मुझे पहले स्थान पर List<ViewModel> दिया गया था, इसलिए मुझे संदेह था कि मैं कैसे यह वैसे भी कर सकता है), मैंने अभी एक नई सूची बनाई है - यदि परिणाम ठीक है तो इसमें परिणाम जोड़ना।

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