À l'aide de LINQ, à partir de a List<int>
, comment puis-je récupérer une liste contenant des entrées répétées plusieurs fois et leurs valeurs?
À l'aide de LINQ, à partir de a List<int>
, comment puis-je récupérer une liste contenant des entrées répétées plusieurs fois et leurs valeurs?
Réponses:
Le moyen le plus simple de résoudre le problème consiste à regrouper les éléments en fonction de leur valeur, puis à choisir un représentant du groupe s'il existe plusieurs éléments dans le groupe. Dans LINQ, cela se traduit par:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
Si vous voulez savoir combien de fois les éléments sont répétés, vous pouvez utiliser:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
Cela renverra un List
de type anonyme, et chaque élément aura les propriétés Element
et Counter
, pour récupérer les informations dont vous avez besoin.
Et enfin, si c'est un dictionnaire que vous recherchez, vous pouvez utiliser
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
Cela retournera un dictionnaire, avec votre élément comme clé, et le nombre de fois qu'il sera répété comme valeur.
code
for (int i = 0; i <duplicates.Count; i ++) {int duplicate = duplicates [i]; duplicatesLocation.Add (duplicate, new List <int> ()); for (int k = 0; k <hitsList.Length; k ++) {if (hitsList [k] .Contains (duplicate)) {duplicatesLocation.ElementAt (i) .Value.Add (k); }} // supprime les doublons selon certaines règles. }code
Découvrez si un énumérable contient des doublons :
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Découvrez si toutes les valeurs d'un énumérable sont uniques :
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
Une autre façon utilise HashSet
:
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
Si vous souhaitez des valeurs uniques dans votre liste de doublons:
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();
Voici la même solution qu'une méthode d'extension générique:
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 }
comme source, le résultat est un IEnumerable<int>
avec un élément ayant la valeur 1
(où la valeur en double correcte est 2)
Console.WriteLine("Count: {0}", duplicates.Count());
directement en dessous et elle s'imprime 6
. À moins que je manque quelque chose sur les exigences de cette fonction, il ne devrait y avoir qu'un seul élément dans la collection résultante.
ToList
afin de résoudre le problème, mais cela signifie que la méthode est exécutée dès son appel, et non lorsque vous parcourez les résultats.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
mènera à une liste qui inclut toutes les occurrences de doublons. Donc, si vous avez quatre occurrences de 2 dans votre liste, votre liste en double contiendra trois occurrences de 2, car une seule des 2 peut être ajoutée au HashSet. Si vous voulez que votre liste contienne des valeurs uniques pour chaque doublon, utilisez plutôt ce code:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
Tu peux le faire:
var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();
Avec ces méthodes d'extension:
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();
}
}
L'utilisation de IsMultiple () dans la méthode Duplicates est plus rapide que Count () car cela n'itère pas toute la collection.
Count()
est pré-calculée et que votre solution est probablement plus lente.
Count()
] est fondamentalement différent de parcourir toute la liste. Count()
est pré-calculé mais l'itération de la liste entière ne l'est pas.
J'ai créé une extension pour répondre à cela, vous pouvez l'inclure dans vos projets, je pense que cela revient le plus souvent lorsque vous recherchez des doublons dans List ou Linq.
Exemple:
//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
*/
}
Pour rechercher uniquement les valeurs en double:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Par exemple. var list = new [] {1,2,3,1,4,2};
donc group by regroupera les nombres par leurs clés et maintiendra le compte (nombre de fois qu'il s'est répété) avec lui. Après cela, nous vérifions simplement les valeurs qui se sont répétées plus d'une fois.
Pour rechercher uniquement les valeurs uniuqe:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Par exemple. var list = new [] {1,2,3,1,4,2};
donc group by regroupera les nombres par leurs clés et maintiendra le compte (nombre de fois qu'il s'est répété) avec lui. Après cela, nous vérifions simplement les valeurs qui n'ont répété qu'une fois que les moyennes sont uniques.
var unique = list.Distinct(x => x)
Ensemble complet d'extensions Linq to SQL des fonctions Duplicates vérifiées dans MS SQL Server. Sans utiliser .ToList () ou IEnumerable. Ces requêtes s'exécutent dans SQL Server plutôt qu'en mémoire. . Les résultats ne reviennent qu'en mémoire.
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()));
}
il y a une réponse mais je n'ai pas compris pourquoi ne fonctionne pas;
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
ma solution est comme ça dans cette situation;
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}