Використовуючи LINQ з List<int>
, як я можу отримати список, який містить записи, повторювані більше одного разу, та їх значення?
Використовуючи LINQ з List<int>
, як я можу отримати список, який містить записи, повторювані більше одного разу, та їх значення?
Відповіді:
Найпростіший спосіб вирішити проблему - згрупувати елементи на основі їх значення, а потім вибрати представника групи, якщо в групі більше одного елемента. У 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());
Це поверне словник із вашим елементом як ключовим та кількістю повторень як значення.
code
for (int i = 0; i <duplicates.Count; i ++) {int duplicate = duplicates [i]; duplicatesLocation.Add (дублікат, новий Список <int> ()); for (int k = 0; k <hitsList.Length; k ++) {if (hitsList [k] .Contains (duplicate)) {duplicatesLocation.ElementAt (i) .Value.Add (k); }} // видаліть дублікати відповідно до деяких правил. }code
З'ясуйте, чи містить перелік число дублікатів :
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)).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)
Console.WriteLine("Count: {0}", duplicates.Count());
прямо під ним і він друкується 6
. Якщо я не пропускаю щось про вимоги до цієї функції, у отриманій колекції має бути лише 1 предмет.
ToList
, щоб виправити проблему, але це означає, що метод виконується, як тільки він викликав, а не тоді, коли ви повторюєте результати.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
призведе до списку, який включає всі зустрічі дублікатів. Отже, якщо у вашому списку є чотири входження 2, то ваш дублікат буде містити три випадки з 2, оскільки до HashSet можна додати лише одне з двох. Якщо ви хочете, щоб ваш список містив унікальні значення для кожного дубліката, використовуйте замість цього код:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
Ви можете зробити це:
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 (), оскільки це не повторює всю колекцію.
Count()
це заздалегідь обчислений і ваше рішення, ймовірно , повільніше.
Count()
] в принципі інший, ніж повторення всього списку. 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
*/
}
Щоб знайти лише дублюючі значення:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Напр. var list = new [] {1,2,3,1,4,2};
тому групувати по групуватиме номери за своїми клавішами та підтримуватиме кількість (кількість разів, яку вона повторювала). Після цього ми просто перевіряємо значення, які повторювались не раз.
Щоб знайти лише значення uniuqe:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Напр. var list = new [] {1,2,3,1,4,2};
тому групувати по групуватиме номери за своїми клавішами та підтримуватиме кількість (кількість разів, яку вона повторювала). Після цього ми просто перевіряємо значення, які повторилися лише один раз, засоби є унікальними.
var unique = list.Distinct(x => x)
Повний набір розширень функцій дублікатів від Linq до 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()));
}
є відповідь, але я не зрозумів, чому це не працює;
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();
}