2013-04-04 5 views
7

मैं दो सूचियों है:अंतर डुप्लिकेट संरक्षण

var list1 = new List<string> { "A", "A", "B", C" }; 
var list2 = new List<string> { "A", "B" }; 

और मैं की तरह

var result = new[] { "A", "C" }; 

एक सूची तैयार करना चाहते हैं कहाँ सूची list1 से सभी तत्वों list2 मैं से हटा दिया है ऐसा नहीं लगता कि Except डुप्लिकेट को हटा देता है, इसके लिए एक लिंक एक्सटेंशन विधि है।

गैर LINQ तरीका यह हो सकता है ऐसा करने के लिए:

var tempList = list1.ToList(); 
foreach(var item in list2) 
{ 
    tempList.Remove(item); 
} 

लेकिन अगर वहाँ एक Linq विस्तार विधि है कि मैं याद किया हो सकता है है मैं सोच रहा हूँ।

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

के बाद से वहाँ शायद नहीं कर रहे हैं किसी भी यहां एक विस्तार विधि मैंने बनाया है।

public static class LinqExtensions 
{ 
    public static IEnumerable<T> RemoveRange<T>(this IEnumerable<T> source, IEnumerable<T> second) 
    { 
     var tempList = source.ToList(); 

     foreach(var item in second) 
     { 
      tempList.Remove(item); 
     } 

     return tempList; 
    } 

    public static IEnumerable<TFirst> RemoveMany<TFirst, TSecond>(this IEnumerable<TFirst> source, IEnumerable<TSecond> second, Func<TSecond, IEnumerable<TFirst>> selector) 
    { 
     var tempList = source.ToList(); 

     foreach(var item in second.SelectMany(selector)) 
     { 
      tempList.Remove(item); 
     } 

     return tempList; 
    } 
} 

उपयोग:

list1.RemoveRange(list2) 

उत्तर

2

अपने उदाहरण को देखते हुए, मुझे लगता है कि आप मतलब है "List2 से सभी तत्वों List1 से हटा दिया":

var lookup2 = list2.ToLookup(str => str); 

var result = from str in list1 
      group str by str into strGroup 
      let missingCount 
        = Math.Max(0, strGroup.Count() - lookup2[strGroup.Key].Count()) 
      from missingStr in strGroup.Take(missingCount) 
      select missingStr; 
+0

सूचियां मनमाने ढंग से आकार में हैं, इसलिए कोई भी बड़ा हो सकता है। – Romoku

+0

सूचियों के सापेक्ष आकारों के बारे में यहां कोई धारणा नहीं है। – Ani

+0

ओह मुझे लगता है कि मैंने आपको "सूची 2 से हटाए गए सूची 2 के सभी तत्वों" से चिह्नित किया है, – Romoku

1

नहीं LINQ, लेकिन एक पंक्ति वैसे भी:

list2.ForEach(l => list1.Remove(l)); 

btw ... यह अच्छा होगा अगर List<int>AddRange लेकिन दूर करने के लिए की तरह कुछ था एक ही समय में वस्तुओं का एक गुच्छा।

1

आप जिस क्रम में परिणाम के तत्वों आने के बारे में परवाह नहीं है, तो आप इसे LINQ के GroupBy के साथ क्या कर सकते हैं:

var a = new List<string>{"A","A", "B", "C"}; 
var b = new List<string>{"A", "B"}; 
var res = a.Select(e => new {Key=e, Val=1}) 
    .Concat(b.Select(e => new {Key=e, Val=-1})) 
    .GroupBy(e => e.Key, e => e.Val) 
    .SelectMany(g => Enumerable.Repeat(g.Key, Math.Max(0, g.Sum()))) 
    .ToList(); 

यहाँ एक demo on ideone है।

मुझे यह स्वीकार करना होगा कि आपका समाधान मेरे मुकाबले कहीं अधिक सरल है, इसलिए इसे केवल जिज्ञासा के रूप में माना जाना चाहिए, यह साबित करने का एक तरीका है कि यह LINQ के साथ भी किया जा सकता है।

यहां बताया गया है कि यह कैसे काम करता है: पहली सूची से प्रत्येक तत्व के लिए हम 1 के साथ एक कुंजी-मूल्य जोड़ी जोड़ते हैं; दूसरी सूची से प्रत्येक तत्व के लिए हम -1 के साथ एक कुंजी-मूल्य जोड़ी जोड़ते हैं। फिर हम सभी तत्वों को उनकी कुंजी से समूहित करते हैं, कुल मिलाकर अपने और नकारात्मक वाले होते हैं, और कुल के रूप में कई चाबियां उत्पन्न करते हैं, यह सुनिश्चित करते हुए कि परिणाम नकारात्मक होने पर हम कुछ भी नहीं चुनते हैं।

+0

खैर यह काम करता है, लेकिन यह है कि अभी जिस तरह अधिक जटिल है। – Romoku

+0

@dasblinkenlight उसे सरल बनाने के लिए एक विस्तार में बदल गया –

+2

मुझे लगता है कि कभी-कभी लिंक सिर्फ जवाब नहीं है। – Romoku

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