J'ai une classe Items
avec properties (Id, Name, Code, Price)
.
La liste de Items
contient des éléments dupliqués.
Pour ex .:
1 Item1 IT00001 $100
2 Item2 IT00002 $200
3 Item3 IT00003 $150
1 Item1 IT00001 $100
3 Item3 IT00003 $150
Comment supprimer les doublons dans la liste en utilisant linq?
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());
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
Si quelque chose rejette votre requête Distinct, vous pouvez consulter MoreLinq , utiliser l'opérateur DistinctBy et sélectionner des objets distincts par id.
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()
tout en gardant à l’esprit que le comparateur d’égalité par défaut permet de 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/library/bb348436.aspx pour un exemple.
Vous avez ici trois options pour supprimer les articles en double de votre liste:
Distinct(new DistinctItemComparer())
comme @Christian Hayter mentionne.Utilisez GroupBy
, mais veuillez noter que dans GroupBy
vous devriez grouper par toutes les colonnes car si vous groupez simplement par Id
, les éléments en double ne seront pas toujours supprimés. 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 pour 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 Equal
et GetHashCode
dans la classe d'objets:
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(g => g.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. Espérons 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)));
}
}
Usage:
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; }
}