सूची में C # LINQ डुप्लिकेट पाते हैं


333

LINQ का उपयोग करते हुए, एक से List<int>, मैं एक सूची कैसे प्राप्त कर सकता हूं जिसमें एक से अधिक बार प्रविष्टियां और उनके मान शामिल हैं?

जवाबों:


567

समस्या को हल करने का सबसे आसान तरीका तत्वों को उनके मूल्य के आधार पर समूहित करना है, और फिर समूह के एक प्रतिनिधि को चुनें, यदि समूह में एक से अधिक तत्व हैं। LINQ में, इसका अनुवाद इस प्रकार है:

var query = lst.GroupBy(x => x)
              .Where(g => g.Count() > 1)
              .Select(y => y.Key)
              .ToList();

यदि आप जानना चाहते हैं कि तत्वों को कितनी बार दोहराया जाता है, तो आप उपयोग कर सकते हैं:

var query = lst.GroupBy(x => x)
              .Where(g => g.Count() > 1)
              .Select(y => new { Element = y.Key, Counter = y.Count() })
              .ToList();

यह Listएक अनाम प्रकार की लौटाएगा , और प्रत्येक तत्व में आपके लिए आवश्यक जानकारी को पुनः प्राप्त करने के लिए गुण होंगे Elementऔर Counter

और अंत में, यदि यह एक ऐसा शब्दकोश है जिसे आप ढूंढ रहे हैं, तो आप उपयोग कर सकते हैं

var query = lst.GroupBy(x => x)
              .Where(g => g.Count() > 1)
              .ToDictionary(x => x.Key, y => y.Count());

यह आपके तत्व के साथ एक शब्दकोष लौटाएगा, और यह मान के रूप में दोहराया जाता है।


अब बस एक आश्चर्य है, मान लीजिए कि डुप्लिकेट किए गए int को n int सरणियों में वितरित किया जाता है, शब्दकोश का उपयोग करने के लिए im और लूप का उपयोग करके यह समझने के लिए कि किस सरणी में एक डुप्लिकेट है और वितरण के एक तर्क के अनुसार इसे हटा दें, क्या सबसे तेज़ तरीका है (linq सोच) उस परिणाम को प्राप्त करें? ब्याज के लिए अग्रिम धन्यवाद।
मिर्को आर्किया

मैं कुछ इस तरह से कर रहा हूँ: code (int i = 0; मैं <डुप्लिकेट ।ाउंट; i ++) {int डुप्लिकेट = डुप्लिकेट [i]; डुप्लिकेटेशन। जोड़ें (डुप्लिकेट, नई सूची <int> ()); for (int k = 0; k <hitsList.Length; k ++) {if (hitsList [k] .Contains (डुप्लिकेट)) {डुप्लीकेट्सलोकेशन .ElementAt (i) .Value.Add (k) }} // कुछ नियमों के अनुसार डुप्लिकेट निकालें। }code
मिर्को आर्कियो

यदि आप सरणियों की एक सूची में डुप्लिकेट ढूंढना चाहते हैं, तो SelectMany को एक रूप दें
सहेजें

मैं सूचियों की एक श्रृंखला में डुप्लिकेट की खोज कर रहा हूं, लेकिन यह पता लगाने में मेरी मदद नहीं की गई है कि इसे बनाने में मेरी मदद कैसे की जाए
Mirko Arcese

1
यह जाँचने के लिए कि क्या किसी संग्रह में एक से अधिक तत्व हैं यदि छोड़ें (1) .Any () के बजाय गणना () का उपयोग करने के लिए अधिक कुशल है। 1000 तत्वों के साथ एक संग्रह की कल्पना करें। छोड़ें (1)। कोई () 2 तत्व का पता लगाने के बाद 1 से अधिक का पता लगाएगा। गणना () का उपयोग करके पूर्ण संग्रह तक पहुंचने की आवश्यकता है।
हेराल्ड कोप्पुलसे

133

पता लगाएँ कि क्या किसी गणनीय में कोई डुप्लिकेट है :

var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);

पता लगाएँ कि क्या किसी गणना योग्य सभी मान अद्वितीय हैं :

var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);

क्या कोई संभावना है कि ये हमेशा बूलियन विरोधी नहीं हैं? anyDuplicate ==! सभी मामलों में सर्वव्यापी।
गर गॉडफ्रे

1
@GarrGodfrey वे हमेशा बूलियन विरोधी होते हैं
Caltor

21

एक और तरीका उपयोग कर रहा है HashSet:

var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));

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

var myhash = new HashSet<int>();
var mylist = new List<int>(){1,1,2,2,3,3,3,4,4,4};
var duplicates = mylist.Where(item => !myhash.Add(item)).Distinct().ToList();

यहाँ जेनेरिक एक्सटेंशन विधि के समान समाधान है:

public static class Extensions
{
  public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)
  {
    var hash = new HashSet<TKey>(comparer);
    return source.Where(item => !hash.Add(selector(item))).ToList();
  }

  public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
  {
    return source.GetDuplicates(x => x, comparer);      
  }

  public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
  {
    return source.GetDuplicates(selector, null);
  }

  public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source)
  {
    return source.GetDuplicates(x => x, null);
  }
}

यह अपेक्षा के अनुरूप काम नहीं करता है। List<int> { 1, 2, 3, 4, 5, 2 }स्रोत के रूप में उपयोग करते हुए , परिणाम IEnumerable<int>एक तत्व के साथ होता है जिसका मान होता है 1(जहां सही डुप्लिकेट मान 2 है)
BCA

@ बीसीए कल, मुझे लगता है कि आप गलत हैं। इस उदाहरण को देखें: dotnetfiddle.net/GUnhUl
HuBeZa

आपका फिडेल सही परिणाम प्रिंट करता है। हालाँकि, मैंने Console.WriteLine("Count: {0}", duplicates.Count());इसके नीचे सीधे लाइन जोड़ी और यह प्रिंट करता है 6। जब तक मैं इस फ़ंक्शन की आवश्यकताओं के बारे में कुछ याद नहीं कर रहा हूं, तब तक परिणामी संग्रह में केवल 1 आइटम होना चाहिए।
बीसीए

@ बीसीए कल, यह LINQ स्थगित निष्पादन के कारण एक बग है। मैंने ToListसमस्या को ठीक करने के लिए जोड़ा है, लेकिन इसका मतलब यह है कि इस विधि को जैसे ही इसे बुलाया जाता है, तब निष्पादित किया जाता है, न कि जब आप परिणामों पर पुनरावृति करते हैं।
HuBeZa

var hash = new HashSet<int>(); var duplicates = list.Where(i => !hash.Add(i));एक ऐसी सूची का नेतृत्व करेगा जिसमें डुप्लिकेट की सभी घटनाएं शामिल हैं। इसलिए यदि आपकी सूची में 2 की चार घटनाएं हैं, तो आपकी डुप्लिकेट सूची में 2 की तीन घटनाएं शामिल होंगी, क्योंकि 2 में से केवल एक को ही हाससेट में जोड़ा जा सकता है। यदि आप चाहते हैं कि आपकी सूची में प्रत्येक डुप्लिकेट के लिए अनन्य मान हों, तो इस कोड का उपयोग करें:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
solid_luffy

10

तुम यह केर सकते हो:

var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();

इन विस्तार विधियों के साथ:

public static class Extensions
{
    public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
    {
        var grouped = source.GroupBy(selector);
        var moreThan1 = grouped.Where(i => i.IsMultiple());
        return moreThan1.SelectMany(i => i);
    }

    public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source)
    {
        return source.Duplicates(i => i);
    }

    public static bool IsMultiple<T>(this IEnumerable<T> source)
    {
        var enumerator = source.GetEnumerator();
        return enumerator.MoveNext() && enumerator.MoveNext();
    }
}

डुप्लिकेट विधि में IsMultiple () का उपयोग करना काउंट () की तुलना में तेज़ है क्योंकि यह पूरे संग्रह को पुनरावृत्त नहीं करता है।


आप को देखो, तो समूहबद्ध करने के लिए संदर्भ स्रोत आप देख सकते हैं कि Count() है अभिकलन पूर्व और अपने समाधान होने की संभावना धीमी है।
जॉनबोट

@Johnbot। आप सही हैं, इस मामले में यह तेज़ है और कार्यान्वयन की संभावना कभी नहीं बदलती है ... लेकिन यह आईजीग्रुपिंग के पीछे इम्प्लांटेशन क्लास के कार्यान्वयन विवरण पर निर्भर करता है। मेरे कार्यान्वयन के साथ, आप जानते हैं कि यह कभी भी पूरे संग्रह को पुनरावृत्त नहीं करेगा।
एलेक्स साइपमैन

इसलिए गिनती [ Count()] मूल रूप से पूरी सूची को पुनरावृत्त करने से अलग है। Count()पूर्व-संगणित है लेकिन संपूर्ण सूची को पुनरावृत्त नहीं करता है।
जोगी

@ कृष्ण खान: मुझे काउंट () और काउंट () के बीच का अंतर समझ में नहीं आता है
एलेक्स साइपमैन

2
@RehanKhan: IsMultiple एक गणना नहीं कर रहा है (), यह 2 आइटम के तुरंत बाद बंद हो जाता है। जैसे टेक (2) .Count> = 2;
एलेक्स साइपमैन

6

मैंने इस पर प्रतिक्रिया देने के लिए एक उद्धरण बनाया, जिसे आप इसे अपनी परियोजनाओं में शामिल कर सकते हैं, मुझे लगता है कि जब आप सूची या लाइनक में डुप्लिकेट खोजते हैं तो यह सबसे अधिक लाभ देता है।

उदाहरण:

//Dummy class to compare in list
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public Person(int id, string name, string surname)
    {
        this.Id = id;
        this.Name = name;
        this.Surname = surname;
    }
}


//The extention static class
public static class Extention
{
    public static IEnumerable<T> getMoreThanOnceRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
    { //Return only the second and next reptition
        return extList
            .GroupBy(groupProps)
            .SelectMany(z => z.Skip(1)); //Skip the first occur and return all the others that repeats
    }
    public static IEnumerable<T> getAllRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
    {
        //Get All the lines that has repeating
        return extList
            .GroupBy(groupProps)
            .Where(z => z.Count() > 1) //Filter only the distinct one
            .SelectMany(z => z);//All in where has to be retuned
    }
}

//how to use it:
void DuplicateExample()
{
    //Populate List
    List<Person> PersonsLst = new List<Person>(){
    new Person(1,"Ricardo","Figueiredo"), //fist Duplicate to the example
    new Person(2,"Ana","Figueiredo"),
    new Person(3,"Ricardo","Figueiredo"),//second Duplicate to the example
    new Person(4,"Margarida","Figueiredo"),
    new Person(5,"Ricardo","Figueiredo")//third Duplicate to the example
    };

    Console.WriteLine("All:");
    PersonsLst.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
        All:
        1 -> Ricardo Figueiredo
        2 -> Ana Figueiredo
        3 -> Ricardo Figueiredo
        4 -> Margarida Figueiredo
        5 -> Ricardo Figueiredo
        */

    Console.WriteLine("All lines with repeated data");
    PersonsLst.getAllRepeated(z => new { z.Name, z.Surname })
        .ToList()
        .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
        All lines with repeated data
        1 -> Ricardo Figueiredo
        3 -> Ricardo Figueiredo
        5 -> Ricardo Figueiredo
        */
    Console.WriteLine("Only Repeated more than once");
    PersonsLst.getMoreThanOnceRepeated(z => new { z.Name, z.Surname })
        .ToList()
        .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
        Only Repeated more than once
        3 -> Ricardo Figueiredo
        5 -> Ricardo Figueiredo
        */
}

1
गणना () के बजाय स्किप (1)। किसी () का उपयोग करने पर विचार करें। यदि आपके पास 1000 डुप्लिकेट हैं, तो स्किप (1)। किसी भी (2) को खोजने के बाद बंद हो जाएगा। गिनती () सभी 1000 तत्वों तक पहुंच जाएगी।
हैराल्ड कोप्पुलसे

1
यदि आप इस एक्सटेंशन विधि को जोड़ते हैं, तो GroupBy के बजाय HashSet.Add का उपयोग करने पर विचार करें, जैसा कि अन्य उत्तरों में से एक में किया गया है। जैसे ही HashSet.Add एक डुप्लिकेट पाता है वह बंद हो जाएगा। आपका GroupBy सभी तत्वों का समूह बनाना जारी रखेगा, भले ही एक से अधिक तत्वों वाला समूह पाया गया हो
Harald Coppoolse

6

केवल डुप्लिकेट मानों को खोजने के लिए:

var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);

उदाहरण के लिए। var सूची = नया [] {1,2,3,1,4,2};

इसलिए समूह अपनी कुंजियों द्वारा संख्याओं को समूह करेगा और इसके साथ गिनती (बार-बार दोहराई जाने वाली संख्या) को बनाए रखेगा। उसके बाद, हम केवल उन मानों की जाँच कर रहे हैं जो एक से अधिक बार दोहराए गए हैं।

केवल यूनीक मूल्यों को खोजने के लिए:

var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);

उदाहरण के लिए। var सूची = नया [] {1,2,3,1,4,2};

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


नीचे दिए गए कोड में अद्वितीय आइटम भी मिलेंगे। var unique = list.Distinct(x => x)
मालू एमएन

1

MS SQL सर्वर में जाँच किए गए डुप्लिकेट फ़ंक्शंस के SQL एक्सटेंशन के लाइनक का पूरा सेट। का उपयोग किए बिना .TLList () या IEnumerable। ये प्रश्न मेमोरी के बजाय SQL सर्वर में निष्पादित होते हैं। । परिणाम केवल स्मृति में वापस आते हैं।

public static class Linq2SqlExtensions {

    public class CountOfT<T> {
        public T Key { get; set; }
        public int Count { get; set; }
    }

    public static IQueryable<TKey> Duplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
        => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);

    public static IQueryable<TSource> GetDuplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
        => source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);

    public static IQueryable<CountOfT<TKey>> DuplicatesCounts<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
        => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT<TKey> { Key = y.Key, Count = y.Count() });

    public static IQueryable<Tuple<TKey, int>> DuplicatesCountsAsTuble<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
        => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
}

0

एक उत्तर है लेकिन मुझे समझ नहीं आया कि काम क्यों नहीं कर रहा है;

var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);

मेरा समाधान इस स्थिति में ऐसा है;

var duplicates = model.list
                    .GroupBy(s => s.SAME_ID)
                    .Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
    doSomething();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.