c# - for - Eliminar duplicados en la lista usando linq
linq select (10)
Así es como pude agruparme con Linq. Espero eso ayude.
var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());
Tengo una clase de Items
con properties (Id, Name, Code, Price)
.
La lista de Items
se rellena con elementos duplicados.
Por ej .:
1 Item1 IT00001 $100
2 Item2 IT00002 $200
3 Item3 IT00003 $150
1 Item1 IT00001 $100
3 Item3 IT00003 $150
¿Cómo eliminar los duplicados en la lista usando linq?
Cuando no quieras escribir IEqualityComparer, puedes intentar algo como seguir.
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; }
}
Pruebe este método de extensión. Esperemos que esto pueda ayudar.
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());
}
}
Uso:
var lstDst = lst.DistinctBy(g => g.Key);
Si hay algo que está descartando su consulta Distinct, es posible que desee consultar MoreLinq y usar el operador DistinctBy y seleccionar objetos distintos por id.
var distinct = items.DistinctBy( i => i.Id );
Tiene tres opciones aquí para eliminar un elemento duplicado en su Lista:
- Use un comparador de igualdad personalizado y luego use
Distinct(new DistinctItemComparer())
como se menciona en @Christian Hayter . Utilice
GroupBy
, pero tenga en cuenta que enGroupBy
debe agrupar por todas las columnas porque si solo agrupa porId
, no siempre se eliminan los elementos duplicados. Por ejemplo, considere el siguiente ejemplo: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());
El resultado de esta agrupación será:
{Id = 1, Name = "Item1", Code = "IT00001", Price = 100} {Id = 2, Name = "Item2", Code = "IT00002", Price = 200} {Id = 3, Name = "Item3", Code = "IT00003", Price = 150}
Lo cual es incorrecto porque considera
{Id = 3, Name = "Item3", Code = "IT00004", Price = 250}
como duplicado. Entonces la consulta correcta sería:var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price}) .Select(c => c.First()).ToList();
3.Override
Equal
andGetHashCode
en la clase de elemento: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(); } }
Entonces puedes usarlo así:
var distinctItems = a.Distinct();
Un método de extensión universal:
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)));
}
}
Ejemplo de uso:
var outputList = sourceList.DistinctBy(x => x.TargetProperty);
Use Distinct()
pero tenga en cuenta que usa el comparador de igualdad predeterminado para comparar valores, por lo que si quiere algo más que eso, necesita implementar su propio comparador.
Consulte http://msdn.microsoft.com/en-us/library/bb348436.aspx para ver un ejemplo.
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();
var distinctItems = items.Distinct();
Para hacer coincidir solo algunas de las propiedades, cree un comparador de igualdad personalizado, por ejemplo:
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();
}
}
Entonces úsalo así:
var distinctItems = items.Distinct(new DistinctItemComparer());
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());