Supprimer les doublons de la liste à l'aide de linq
-
05-07-2019 - |
Question
J'ai une classe Articles
avec propriétés (Id, Nom, Code, Prix)
.
La liste des éléments
contient des éléments dupliqués.
Par exemple:
1 Item1 IT00001 $100
2 Item2 IT00002 $200
3 Item3 IT00003 $150
1 Item1 IT00001 $100
3 Item3 IT00003 $150
Comment supprimer les doublons de la liste avec linq?
La solution
var distinctItems = items.Distinct();
Pour ne faire correspondre que certaines propriétés, créez un comparateur d'égalité personnalisé, par exemple:
.class DistinctItemComparer : IEqualityComparer<Item> {
public bool Equals(Item x, Item y) {
return x.Id == y.Id &&
x.Name == y.Name &&
x.Code == y.Code &&
x.Price == y.Price;
}
public int GetHashCode(Item obj) {
return obj.Id.GetHashCode() ^
obj.Name.GetHashCode() ^
obj.Code.GetHashCode() ^
obj.Price.GetHashCode();
}
}
Ensuite, utilisez-le comme ceci:
var distinctItems = items.Distinct(new DistinctItemComparer());
Autres conseils
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
Si quelque chose rejette votre requête Distinct, consultez MoreLinq et utilisez l'opérateur DistinctBy pour sélectionner des objets distincts par identifiant.
var distinct = items.DistinctBy( i => i.Id );
C’est ainsi que j’ai pu grouper avec Linq. J'espère que ça aide.
var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());
Utilisez Distinct ()
, mais n'oubliez pas qu'il utilise le comparateur d'égalité par défaut pour comparer les valeurs. Par conséquent, si vous souhaitez utiliser autre chose que cela, vous devez implémenter votre propre comparateur.
Veuillez consulter http://msdn.microsoft.com/en-us/ bibliothèque / bb348436.aspx pour un exemple.
Vous avez ici trois options pour supprimer les éléments en double de votre liste:
- Utilisez un comparateur d'égalité personnalisé, puis utilisez
Distinct (new DistinctItemComparer ())
comme @Christian Hayter mentionné. -
Utilisez
GroupBy
, mais veuillez noter que dansGroupBy
, vous devez regrouper toutes les colonnes, car si vous ne faites que grouper parId
il ne supprime pas toujours les éléments en double. Par exemple, considérons l'exemple suivant:List<Item> a = new List<Item> { new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}, new Item {Id = 2, Name = "Item2", Code = "IT00002", Price = 200}, new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}, new Item {Id = 1, Name = "Item1", Code = "IT00001", Price = 100}, new Item {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}, new Item {Id = 3, Name = "Item3", Code = "IT00004", Price = 250} }; var distinctItems = a.GroupBy(x => x.Id).Select(y => y.First());
Le résultat de ce regroupement sera:
{Id = 1, Name = "Item1", Code = "IT00001", Price = 100} {Id = 2, Name = "Item2", Code = "IT00002", Price = 200} {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}
Ce qui est incorrect car il considère que
{Id = 3, Name = "Item3", Code = "IT00004", Price = 250}
est dupliqué. Donc, la requête correcte serait:var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price}) .Select(c => c.First()).ToList();
3.Override
Égal
etGetHashCode
dans la classe de poste:public class Item { public int Id { get; set; } public string Name { get; set; } public string Code { get; set; } public int Price { get; set; } public override bool Equals(object obj) { if (!(obj is Item)) return false; Item p = (Item)obj; return (p.Id == Id && p.Name == Name && p.Code == Code && p.Price == Price); } public override int GetHashCode() { return String.Format("{0}|{1}|{2}|{3}", Id, Name, Code, Price).GetHashCode(); } }
Ensuite, vous pouvez l'utiliser comme ceci:
var distinctItems = a.Distinct();
Une méthode d'extension universelle:
public static class EnumerableExtensions
{
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> keySelector)
{
return enumerable.GroupBy(keySelector).Select(grp => grp.First());
}
}
Exemple d'utilisation:
var lstDst = lst.DistinctBy(item => item.Key);
List<Employee> employees = new List<Employee>()
{
new Employee{Id =1,Name="AAAAA"}
, new Employee{Id =2,Name="BBBBB"}
, new Employee{Id =3,Name="AAAAA"}
, new Employee{Id =4,Name="CCCCC"}
, new Employee{Id =5,Name="AAAAA"}
};
List<Employee> duplicateEmployees = employees.Except(employees.GroupBy(i => i.Name)
.Select(ss => ss.FirstOrDefault()))
.ToList();
Essayez cette méthode d’extension. J'espère que cela pourrait aider.
public static class DistinctHelper
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var identifiedKeys = new HashSet<TKey>();
return source.Where(element => identifiedKeys.Add(keySelector(element)));
}
}
Utilisation:
var outputList = sourceList.DistinctBy(x => x.TargetProperty);
Lorsque vous ne voulez pas écrire IEqualityComparer, vous pouvez essayer quelque chose comme suit.
class Program
{
private static void Main(string[] args)
{
var items = new List<Item>();
items.Add(new Item {Id = 1, Name = "Item1"});
items.Add(new Item {Id = 2, Name = "Item2"});
items.Add(new Item {Id = 3, Name = "Item3"});
//Duplicate item
items.Add(new Item {Id = 4, Name = "Item4"});
//Duplicate item
items.Add(new Item {Id = 2, Name = "Item2"});
items.Add(new Item {Id = 3, Name = "Item3"});
var res = items.Select(i => new {i.Id, i.Name})
.Distinct().Select(x => new Item {Id = x.Id, Name = x.Name}).ToList();
// now res contains distinct records
}
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
}