Pregunta

Tengo un Items de clase con propiedades (Id, Name, Code, Price) .

La lista de elementos 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?

¿Fue útil?

Solución

var distinctItems = items.Distinct();

Para hacer coincidir solo algunas de las propiedades, crea 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());

Otros consejos

var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());

Si hay algo que está descartando su consulta de Distinct, puede consultar Haga clic en MoreLinq y use el operador DistinctBy para seleccionar objetos distintos por id.

var distinct = items.DistinctBy( i => i.Id );

Así es como pude agruparme con Linq. Espero que ayude.

var query = collection.GroupBy(x => x.title).Select(y => y.FirstOrDefault());

Use Distinct () pero tenga en cuenta que utiliza el comparador de igualdad predeterminado para comparar valores, por lo que si desea algo más que eso, necesita implementar su propio comparador.

Consulte http://msdn.microsoft.com/en-us/ library / bb348436.aspx para un ejemplo.

Aquí tiene tres opciones para eliminar un elemento duplicado en su Lista:

  1. Use un comparador de igualdad personalizado y luego use Distinct (nuevo DistinctItemComparer ()) como @Christian Hayter mencionado.
  2. Usa GroupBy , pero ten en cuenta que en GroupBy debes agrupar por todas las columnas porque si solo agrupas por Id no elimina elementos duplicados siempre. 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 que {Id = 3, Name = " Item3 " ;, Code = " IT00004 " ;, Price = 250} como duplicado. Así que 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 y GetHashCode 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 EnumerableExtensions
{
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> keySelector)
    {
        return enumerable.GroupBy(keySelector).Select(grp => grp.First());
    }
}

Ejemplo de uso:

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();

Prueba este método de extensión. Esperemos que esto pueda ayudar.

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)));
    }
}

Uso:

var outputList = sourceList.DistinctBy(x => x.TargetProperty);

Cuando no quieras escribir IEqualityComparer, puedes intentar algo como lo siguiente.

 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; }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top