Pergunta

Eu tenho um Items classe com properties (Id, Name, Code, Price).

A Lista de Items é preenchida com itens duplicados.

Por ex .:

1         Item1       IT00001        $100
2         Item2       IT00002        $200
3         Item3       IT00003        $150
1         Item1       IT00001        $100
3         Item3       IT00003        $150

Como remover as duplicatas na lista usando o LINQ?

Foi útil?

Solução

var distinctItems = items.Distinct();

Para corresponder apenas em algumas das propriedades, criar um comparador de igualdade personalizado, por exemplo:.

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

Em seguida, usá-lo como este:

var distinctItems = items.Distinct(new DistinctItemComparer());

Outras dicas

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

Se há algo que está jogando fora sua consulta distinta, você pode querer olhar em MoreLINQ e usar o operador DistinctBy e selecionar objetos distintos por id.

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

Isto é como eu era capaz de grupo, com Linq. Espero que ajude.

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

Use Distinct() mas tenha em mente que ele usa o comparador de igualdade padrão para comparar valores, por isso, se você quer nada além do que você precisa para implementar seu próprio comparador.

Por favor, veja http://msdn.microsoft.com/en-us/ biblioteca / bb348436.aspx para um exemplo.

Você tem três opções aqui para remover item duplicado na sua lista:

  1. Use a um comparador de igualdade personalizado e, em seguida, usar Distinct(new DistinctItemComparer()) como @Christian Hayter mencionado.
  2. Use GroupBy, mas nota por favor em GroupBy que deveria Grupo por todas as colunas, porque se você só grupo por Id não remover itens duplicados sempre. Por exemplo, considere o seguinte exemplo:

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

    O resultado para este agrupamento 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}
    

    O que é incorreta porque considera {Id = 3, Name = "Item3", Code = "IT00004", Price = 250} como duplicado. Assim, a consulta correta seria:

    var distinctItems = a.GroupBy(c => new { c.Id , c.Name , c.Code , c.Price})
                         .Select(c => c.First()).ToList();
    

    3.Override Equal e GetHashCode na classe de item:

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

    Em seguida, você pode usá-lo como este:

    var distinctItems = a.Distinct();
    

Um método de extensão 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());
    }
}

Exemplo de utilização:

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

Tente este método de extensão para fora. Esperemos que isto poderia ajudar.

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

Quando você não quer escrever IEqualityComparer você pode tentar 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; }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top