6 ответов:
самый простой способ решить проблему-сгруппировать элементы на основе их значения, а затем выбрать представителя группы, если в группе есть более одного элемента. В 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();это вернет a
Listанонимный тип, и каждый элемент будет иметь свойстваElementиCounter, чтобы получить информацию, которую вы необходимость.и наконец, если это словарь, который вы ищете, вы можете использовать
var query = lst.GroupBy(x => x) .Where(g => g.Count() > 1) .ToDictionary(x => x.Key, y => y.Count());это вернет словарь, с вашим элементом в качестве ключа, и количество раз, когда он повторяется как значение.
узнайте, содержит ли перечисляемый любые повторяющиеся:
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);выяснить, если все значения в перечислимомуникальный:
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
другой способ-это использование
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)).ToList().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); } }
Вы можете сделать это:
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() в методе Duplicates быстрее, чем Count (), потому что это не повторяет всю коллекцию.
Я создал расширение для ответа на это вы могли бы включить его в свои проекты, я думаю, что это возвращение в большинстве случаев, когда вы ищете дубликаты в List или Linq.
пример:
//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 */ }
полный набор расширений Linq to SQL дубликатов функций, проверенных в MS SQL Server. Без использования. ToList () или IEnumerable. эти запросы выполняются в SQL Server, а не в памяти.. Результаты возвращаются только в памяти.
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())); }
Comments