लाइनक का उपयोग करके सूची में डुप्लिकेट निकालें


313

मेरे Itemsसाथ एक क्लास है properties (Id, Name, Code, Price)

Itemsडुप्लिकेट आइटम के साथ सूची की आबादी है।

पूर्व के लिए:

1         Item1       IT00001        $100
2         Item2       IT00002        $200
3         Item3       IT00003        $150
1         Item1       IT00001        $100
3         Item3       IT00003        $150

लाइनक का उपयोग करके सूची में डुप्लिकेट कैसे निकालें?


मेरे पास आइटम क्लास में संपत्ति के रूप में एक और वर्ग भी है
प्रसाद

आप यह भी कर सकते हैं var set = new HashSet<int>(); var uniques = items.Where(x => set.Add(x.Id));। ऐसा करने के लिए आपराधिक होना चाहिए ..
nawfal

जवाबों:


394
var distinctItems = items.Distinct();

केवल कुछ गुणों पर मिलान करने के लिए, एक कस्टम समानता तुलना बनाएँ, जैसे:

class DistinctItemComparer : IEqualityComparer<Item> {

    public bool Equals(Item x, Item y) {
        return x.Id == y.Id &&
            x.Name == y.Name &&
            x.Code == y.Code &&
            x.Price == y.Price;
    }

    public int GetHashCode(Item obj) {
        return obj.Id.GetHashCode() ^
            obj.Name.GetHashCode() ^
            obj.Code.GetHashCode() ^
            obj.Price.GetHashCode();
    }
}

फिर इसे इस तरह उपयोग करें:

var distinctItems = items.Distinct(new DistinctItemComparer());

हाय क्रिश्चियन, अगर मेरे पास एक सूची <my_Custom_Class> और सूची <string> है तो कोड में क्या बदलाव होगा। मेरे कस्टम वर्ग में विभिन्न आइटम हैं जिनमें से एक DCN नंबर है और सूची <string> में केवल DCN नंबर है। इसलिए मुझे सूची की जाँच करने की आवश्यकता है <Custom_Class> में सूची <string> से कोई dcn शामिल है। उदाहरण के लिए मान लीजिए List1 = सूची <Custom_Class> और List2 = सूची <स्ट्रिंग>। यदि List1 में 2000 आइटम हैं और list2 में 40000 आइटम हैं, जिस पर List1 से 600 आइटम List2 में मौजूद हैं। तो इस मामले में मुझे सूची 1 के रूप में मेरी आउटपुट सूची के रूप में 1400 की आवश्यकता है। तो अभिव्यक्ति क्या होगी। अग्रिम धन्यवाद

इसके अलावा एक और मामला यहाँ है क्योंकि List1 में विभिन्न आइटम हैं, अन्य आइटम मान भिन्न हो सकते हैं लेकिन DCN समान होना चाहिए। तो मेरे मामले में डिस्टिंक्ट वांछित पुट देने में विफल रहे।

2
मुझे तुलनात्मक कक्षाएं अत्यंत उपयोगी लगती हैं। वे साधारण संपत्ति के नाम की तुलना के अलावा तर्क व्यक्त कर सकते हैं। मैंने पिछले महीने एक नया लिखा, कुछ ऐसा करने के लिए जो GroupByनहीं कर सकता था।
ईसाई हैटर

अच्छी तरह से काम करता है और मुझे कुछ नया सीखने और C # में XoRऑपरेटर की जांच करने के लिए मिला है ^। के माध्यम से VB.NET में इस्तेमाल किया गया Xorथा, लेकिन पहले यह क्या था यह देखने के लिए अपने कोड को दोहरा लेना था।
atconway

यह वह त्रुटि है जो मुझे तब मिलती है जब मैं डिस्टिक्ट कम्पेरिज़र का उपयोग करने का प्रयास करता हूं: "LINQ से एंटिटीज पद्धति को नहीं पहचानता 'System.Linq.IQueryable 1[DataAccess.HR.Dao.CCS_LOCATION_TBL] Distinct[CCS_LOCATION_TBL](System.Linq.IQueryable1 [DataAccess.HR.Dao.CCS_LOCATION_TBL], System .Collections.Generic.IEqualityComparer`1 [ DataAccess.HR.Dao.CCS_LOCATION_TBL]) विधि, और इस विधि का स्टोर अभिव्यक्ति में अनुवाद नहीं किया जा सकता है।
user8128167

600
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());

28
धन्यवाद - एक तुलनात्मक वर्ग लिखने से बचना चाह रहा था इसलिए मुझे खुशी है कि यह काम :)
जेन

8
+1 यह समाधान एक टाई ब्रेकर के लिए भी अनुमति देता है: मानदंड के साथ डुप्लिकेट को समाप्त करें!
एड्रियानो कारनेइरो

4
लेकिन थोड़ा उपरवाला!
अमीरहोसिन मेहरवेजी

1
लेकिन, जैसा कि विक्टर जुरी ने नीचे सुझाया है: फर्स्ट डॉयरफॉल्ट का उपयोग करें। विश्वास नहीं हो सकता है, यह समाधान इतना सरल हो सकता है (बिना कस्टम समानता के तुलना के)
साइबर हॉक

6
आप कई गुणों के साथ समूह बना सकते हैं: सूची <XYZ> MyUniqueList = MyList.GroupBy (x => नया {x.Column1, x.Column2})। चयन करें (जी => girst। ())। ToList ()
सुमित जोशी

40

यदि कोई ऐसी चीज़ है जो आपकी डिस्टिक्ट क्वेरी को फेंक रही है, तो आप MoreLinq को देखना चाहते हैं और डिस्टिक्टबाइ ऑपरेटर का उपयोग कर सकते हैं और आईडी द्वारा अलग-अलग ऑब्जेक्ट का चयन कर सकते हैं ।

var distinct = items.DistinctBy( i => i.Id );

1
Linq के साथ कोई DistinctBy () विधि नहीं है।
फेरेयुडून बारिकज़ेहि

7
@FereydoonBarikzehy लेकिन वह शुद्ध Linq के बारे में बात नहीं कर रहा है। पोस्ट में MoreLinq परियोजना के लिए LINQ है ...
Ademar

30

इस तरह से मैं Linq के साथ समूह में सक्षम था। आशा है ये मदद करेगा।

var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());

3
@ नवाफल, मैं पहले के बदले FirstOrDefault () का सुझाव दे रहा था ()
sobelito

23
यदि मैं सही हूं, तो FirstOrDefaultयहां का उपयोग करने से कोई लाभ नहीं होता है यदि Selectतुरंत अनुसरण किया जाए GroupBy, क्योंकि वहाँ एक खाली समूह होने की कोई संभावना नहीं है (समूह केवल संग्रह की सामग्री से प्राप्त किए गए थे )
रॉय टिंकर

17

उपयोग Distinct() लेकिन ध्यान रखें कि यह मूल्यों की तुलना करने के लिए डिफ़ॉल्ट समानता तुलनित्र का उपयोग करता है, इसलिए यदि आप इससे परे कुछ भी चाहते हैं तो आपको अपने समकक्ष तुलना को लागू करने की आवश्यकता है।

कृपया एक उदाहरण के लिए http://msdn.microsoft.com/en-us/library/bb348436.aspx देखें ।


मुझे ध्यान देना चाहिए कि यदि संग्रह सदस्य प्रकार मान प्रकारों में से एक है तो डिफ़ॉल्ट तुलनित्र काम करता है। लेकिन संदर्भ प्रकारों के लिए csc द्वारा कौन सा डिफ़ॉल्ट समानता तुलनित्र का चयन किया जाता है। संदर्भ प्रकारों का स्वयं का तुलनात्मक होना आवश्यक है।
नूरी YILMAZ

16

आपकी सूची में डुप्लिकेट आइटम को हटाने के लिए आपके पास यहां तीन विकल्प हैं:

  1. एक कस्टम समानता तुलना का उपयोग करें और फिर @Christian हैटर केDistinct(new DistinctItemComparer()) रूप में उपयोग करें ।
  2. उपयोग करें GroupBy, लेकिन कृपया ध्यान दें कि GroupByआपको सभी कॉलमों के अनुसार समूह बनाना चाहिए क्योंकि यदि आप इसके द्वारा समूह Idबनाते हैं तो हमेशा डुप्लिकेट आइटम नहीं निकालते हैं। उदाहरण के लिए निम्नलिखित उदाहरण पर विचार करें:

    List<Item> a = new List<Item>
    {
        new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100},
        new Item {Id = 2, Name = "Item2", Code = "IT00002", Price = 200},
        new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150},
        new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100},
        new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150},
        new Item {Id = 3, Name = "Item3", Code = "IT00004", Price = 250}
    };
    var distinctItems = a.GroupBy(x => x.Id).Select(y => y.First());

    इस समूह के लिए परिणाम होगा:

    {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}
    {Id = 2, Name = "Item2", Code = "IT00002", Price = 200}
    {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}

    जो गलत है क्योंकि इसे {Id = 3, Name = "Item3", Code = "IT00004", Price = 250}डुप्लिकेट माना जाता है। तो सही क्वेरी होगी:

    var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price})
                         .Select(c => c.First()).ToList();

    3.Override Equalऔर GetHashCodeआइटम वर्ग में:

    public class Item
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Code { get; set; }
        public int Price { get; set; }
    
        public override bool Equals(object obj)
        {
            if (!(obj is Item))
                return false;
            Item p = (Item)obj;
            return (p.Id == Id && p.Name == Name && p.Code == Code && p.Price == Price);
        }
        public override int GetHashCode()
        {
            return String.Format("{0}|{1}|{2}|{3}", Id, Name, Code, Price).GetHashCode();
        }
    }

    तो आप इसे इस तरह से उपयोग कर सकते हैं:

    var distinctItems = a.Distinct();

11

एक सार्वभौमिक विस्तार विधि:

public static class EnumerableExtensions
{
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> keySelector)
    {
        return enumerable.GroupBy(keySelector).Select(grp => grp.First());
    }
}

उपयोग का उदाहरण:

var lstDst = lst.DistinctBy(item => item.Key);

बहुत साफ दृष्टिकोण
स्टीवन रिससर्ट

4

इस विस्तार विधि को आज़माएँ। उम्मीद है कि यह मदद कर सकता है।

public static class DistinctHelper
{
    public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        var identifiedKeys = new HashSet<TKey>();
        return source.Where(element => identifiedKeys.Add(keySelector(element)));
    }
}

उपयोग:

var outputList = sourceList.DistinctBy(x => x.TargetProperty);

3
List<Employee> employees = new List<Employee>()
{
    new Employee{Id =1,Name="AAAAA"}
    , new Employee{Id =2,Name="BBBBB"}
    , new Employee{Id =3,Name="AAAAA"}
    , new Employee{Id =4,Name="CCCCC"}
    , new Employee{Id =5,Name="AAAAA"}
};

List<Employee> duplicateEmployees = employees.Except(employees.GroupBy(i => i.Name)
                                             .Select(ss => ss.FirstOrDefault()))
                                            .ToList();

0

एक और समाधान, सुंदर खरीदने योग्य नहीं है।

मेरे पास एक XML फ़ाइल है जिसमें "MEMDES" नामक एक तत्व है जिसमें RAM विशेषता जानकारी दर्ज करने के लिए "GRADE" और "SPD" के रूप में दो विशेषता है। एसपीडी में बहुत सारे डुप्लीकेट आइटम हैं।

तो यहाँ कोड है जिसका उपयोग मैं छपी हुई वस्तुओं को हटाने के लिए करता हूँ:

        IEnumerable<XElement> MList =
            from RAMList in PREF.Descendants("MEMDES")
            where (string)RAMList.Attribute("GRADE") == "DDR4"
            select RAMList;

        List<string> sellist = new List<string>();

        foreach (var MEMList in MList)
        {
            sellist.Add((string)MEMList.Attribute("SPD").Value);
        }

        foreach (string slist in sellist.Distinct())
        {
            comboBox1.Items.Add(slist);
        }

-1

जब आप IEqualityComparer लिखना नहीं चाहते हैं तो आप कुछ इस तरह की कोशिश कर सकते हैं।

 class Program
{

    private static void Main(string[] args)
    {

        var items = new List<Item>();
        items.Add(new Item {Id = 1, Name = "Item1"});
        items.Add(new Item {Id = 2, Name = "Item2"});
        items.Add(new Item {Id = 3, Name = "Item3"});

        //Duplicate item
        items.Add(new Item {Id = 4, Name = "Item4"});
        //Duplicate item
        items.Add(new Item {Id = 2, Name = "Item2"});

        items.Add(new Item {Id = 3, Name = "Item3"});

        var res = items.Select(i => new {i.Id, i.Name})
            .Distinct().Select(x => new Item {Id = x.Id, Name = x.Name}).ToList();

        // now res contains distinct records
    }



}


public class Item
{
    public int Id { get; set; }

    public string Name { get; set; }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.