C # LINQ encontra duplicatas na lista

Usando LINQ, de uma List , como recuperar uma lista que contém inputs repetidas mais de uma vez e seus valores?

A maneira mais fácil de resolver o problema é agrupar os elementos com base em seu valor e, em seguida, escolher um representante do grupo se houver mais de um elemento no grupo. No LINQ, isso se traduz em:

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

Se você quiser saber quantas vezes os elementos são repetidos, você pode usar:

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

Isto irá retornar uma List de um tipo anônimo, e cada elemento terá as propriedades Element e Counter , para recuperar as informações que você precisa.

E, finalmente, se é um dictionary que você está procurando, você pode usar

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

Isso retornará um dictionary, com seu elemento como chave e o número de vezes que ele é repetido como valor.

Descubra se um enumerável contém alguma duplicata :

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

Descubra se todos os valores em um enumerável são exclusivos :

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

Outra maneira é usar o HashSet :

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

Se você quiser valores exclusivos na sua lista de duplicatas:

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

Aqui está a mesma solução que um método de extensão genérico:

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

Você consegue fazer isso:

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

Com estes methods de extensão:

 public static class Extensions { public static IEnumerable Duplicates(this IEnumerable source, Func selector) { var grouped = source.GroupBy(selector); var moreThan1 = grouped.Where(i => i.IsMultiple()); return moreThan1.SelectMany(i => i); } public static IEnumerable Duplicates(this IEnumerable source) { return source.Duplicates(i => i); } public static bool IsMultiple(this IEnumerable source) { var enumerator = source.GetEnumerator(); return enumerator.MoveNext() && enumerator.MoveNext(); } } 

Usando IsMultiple () no método Duplicates é mais rápido que Count () porque isso não itera a coleção inteira.

Eu criei uma extensão para responder a isso você poderia incluí-lo em seus projetos, acho que isso retorna mais caso quando você procura por duplicatas em List ou Linq.

Exemplo:

 //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 getMoreThanOnceRepeated(this IEnumerable extList, Func 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 getAllRepeated(this IEnumerable extList, Func 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 PersonsLst = new List(){ 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 */ } 

Conjunto completo de extensões Linq de [Duplicatas] com input no MS SQL Server

 public static class LinqExtensions { public class CounterOfT { public T Key { get; set; } public int Count { get; set; } } public static IQueryable Duplicates(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key).AsQueryable(); public static IQueryable GetDuplicates(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s).AsQueryable(); public static IQueryable> DuplicatesCounts(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CounterOfT { Key = y.Key, Count = y.Count() }).AsQueryable(); public static IQueryable> DuplicatesCountsAsTuble(this IEnumerable source, Func groupBy) where TSource : class => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count())).AsQueryable(); }