本文翻译自:C# LINQ find duplicates in List
使用LINQ,如何从List<int>
检索包含重复项不止一次及其值的列表?
#1楼
参考:/question/1fP0S/C-LINQ在列表中查找重复项
#2楼
The easiest way to solve the problem is to group the elements based on their value, and then pick a representative of the group if there are more than one element in the group.解决问题的最简单方法是根据元素的值对其进行分组,如果组中有多个元素,则选择该组的代表。In LINQ, this translates to:在LINQ中,这转换为:
var query = lst.GroupBy(x => x).Where(g => g.Count() > 1).Select(y => y.Key).ToList();
If you want to know how many times the elements are repeated, you can use:如果您想知道元素重复了多少次,可以使用:
var query = lst.GroupBy(x => x).Where(g => g.Count() > 1).Select(y => new { Element = y.Key, Counter = y.Count() }).ToList();
This will return aList
of an anonymous type, and each element will have the propertiesElement
andCounter
, to retrieve the information you need.这将返回一个匿名类型的List
,并且每个元素都将具有属性Element
和Counter
,以检索所需的信息。
And lastly, if it's a dictionary you are looking for, you can use最后,如果您要查找的是字典,则可以使用
var query = lst.GroupBy(x => x).Where(g => g.Count() > 1).ToDictionary(x => x.Key, y => y.Count());
This will return a dictionary, with your element as key, and the number of times it's repeated as value.这将返回一个字典,将您的元素作为键,并将其重复的次数作为值。
#3楼
You can do this:你可以这样做:
var list = new[] {1,2,3,1,4,2};var duplicateItems = list.Duplicates();
With these extension methods:使用这些扩展方法:
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();}}
Using IsMultiple() in the Duplicates method is faster than Count() because this does not iterate the whole collection.在Duplicates方法中使用IsMultiple()比Count()更快,因为这不会迭代整个集合。
#4楼
Another way is usingHashSet
:另一种方法是使用HashSet
:
var hash = new HashSet<int>();var duplicates = list.Where(i => !hash.Add(i));
If you want unique values in your duplicates list:如果要在重复项列表中使用唯一值:
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)).ToList().Distinct().ToList();
Here is the same solution as a generic extension method:这是与通用扩展方法相同的解决方案:
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);}}
#5楼
Find out if an enumerable containsany duplicate:找出可枚举是否包含任何重复项:
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Find out ifallvalues in an enumerable areunique:找出可枚举中的所有值是否唯一:
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
#6楼
I created a extention to response to this you could includ it in your projects, I think this return the most case when you search for duplicates in List or Linq.我创建了一个扩展名以响应此问题,您可以将其包括在项目中,我认为当您在List或Linq中搜索重复项时,这种情况最常见。
Example:例:
//Dummy class to compare in listpublic 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 classpublic 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 reptitionreturn 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 repeatingreturn 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 ListList<Person> PersonsLst = new List<Person>(){new Person(1,"Ricardo","Figueiredo"), //fist Duplicate to the examplenew Person(2,"Ana","Figueiredo"),new Person(3,"Ricardo","Figueiredo"),//second Duplicate to the examplenew 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 Figueiredo2 -> Ana Figueiredo3 -> Ricardo Figueiredo4 -> Margarida Figueiredo5 -> 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 data1 -> Ricardo Figueiredo3 -> Ricardo Figueiredo5 -> 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 once3 -> Ricardo Figueiredo5 -> Ricardo Figueiredo*/}