2013-10-04 11 views
16

का उपयोग कर संपत्ति पर छेड़छाड़ की गई सूची से आइटम निकालें। मेरे पास विभिन्न ऑब्जेक्ट्स की 2 सूचियां हैं (foo & bar) जो वही संपत्ति साझा करती है उसे id पर कॉल करने दें।लिंक

public List<foo> foo { get; set; } 
public List<bar> bar { get; set; } 

मैं foo एक आईडी कि bar

में मौजूद नहीं है यह कैसे LINQ में किया जा सकता है से सभी वस्तुओं हटाना चाहते हैं? मैं Intersect, RemoveAll & Join देख रहा हूं लेकिन कोई उदाहरण नहीं मिल सकता है जहां सूचियां एक अलग प्रकार के हैं।

उत्तर

23

इस प्रयास करें: यदि आइटम bar संग्रह में है

foo.RemoveAll(x=> !bar.Any(y=>y.Id==x.Id)); 

!bar.Any(y=>y.Id==x.Id) मिल जाएगा और अगर ऐसा नहीं है, यह foo संग्रह से निकाल देंगे।

बेहतर समाधान HashSet का उपयोग कर हे (एन): दूसरा जवाब का

var idsNotToBeRemoved = new HashSet<int>(bar.Select(item => item.Id));                      
foo.RemoveAll(item => !idsNotToBeRemoved.Contains(item.Id)); 

स्रोत: https://stackoverflow.com/a/4037674/1714342

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

रूप @Carra ने कहा, पहले समाधान छोटे सूचियों और दूसरे के लिए अच्छा है बड़ी सूचियों के लिए अधिक कुशल है।

+1

शानदार @ wudzik – ojhawkins

+2

छोटी सूचियों के लिए, पहला होगा। यदि आप बड़ी सूचियों का उपयोग कर रहे हैं (> 100 या तो), तो आप दूसरे समाधान का उपयोग करने के बेहतर हैं। – Carra

7
var foo = foo.Where(f => !bar.Any(b => b.Id == f.Id)).ToList(); 

बस ध्यान रखें कि यह एक ओ (n²) समाधान है, यह बड़ा सूचियों के लिए बहुत अच्छी तरह से काम नहीं करेगा।

+0

इसका अधिक प्रभावशाली समाधान क्या होगा? @ कररा – ojhawkins

+0

@ojhawkins एक समाधान 'आईडी' की सूची को हैशसेट (ओ (एन) में पूर्व-संग्रहित करना होगा, फिर प्रत्येक तत्व को 'foo' में उस (ओ (एन)) की तुलना करें 'foo' –

+0

में प्रत्येक तत्व के लिए 'बार' सूची चलने से पहले हाँ मैंने जॉन स्कीट्स उदाहरण को यहां देखा लेकिन यह मेरे उदाहरण पर लागू नहीं हो सकता http://stackoverflow.com/questions/853526/using-linq-to-remove -objects-in-a-listt – ojhawkins