web-dev-qa-db-fra.com

Supprimer les doublons dans la liste à l'aide de linq

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?

252
Prasad
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());
339
Christian Hayter
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
522
Freddy

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

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());
26
Victor Juri

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. 

15
Brian Rasmussen

Vous avez ici trois options pour supprimer les articles en double de votre liste:

  1. Utilisez un comparateur d’égalité personnalisé, puis utilisez Distinct(new DistinctItemComparer()) comme @Christian Hayter mentionne.
  2. 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();
    
12
S.Akbari

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);
3
TOL
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();
3
Arun Kumar

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);
3
Kent Aguilar

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; }
}
0
Kundan Bhati