web-dev-qa-db-fra.com

Comment obtenir une liste distincte à partir d'une liste d'objets?

J'ai un List<MyClass> someList.

class MyClass
{
    public int Prop1...
    public int Prop2...
    public int Prop3...
}

J'aimerais savoir comment obtenir un nouveau List<MyClass> distinctList distinct de List<MyClass> someList, mais en le comparant uniquement à Prop2.

40
Willem

Malheureusement, il n’existe pas de support intégré très simple pour cela dans le cadre - mais vous pouvez utiliser le DistinctBy implementation que j'ai dans MoreLINQ .

Vous utiliseriez:

var distinctList = someList.DistinctBy(x => x.Prop2).ToList();

(Vous pouvez ne prendre que l'implémentation DistinctBy. Si vous préférez utiliser une implémentation Microsoft, je pense qu'il y a quelque chose de similaire dans l'assembly System.Interactive de Reactive Extensions .)

41
Jon Skeet

Vous pouvez émuler l'effet de DistinctBy à l'aide de GroupBy, puis simplement à l'aide de la première entrée de chaque groupe. Cela pourrait être un peu plus lent que les autres implémentations.

someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());
79
CodesInChaos

vous devez utiliser la méthode d'extension .Distinct(..); . Voici un exemple rapide:

public class Comparer : IEqualityComparer<Point>
    {
        public bool Equals(Point x, Point y)
        {
            return x.X == y.X;
        }

        public int GetHashCode(Point obj)
        {
            return (int)obj.X;
        }
    }

Ne pas oublier de GetHashCode.

Usage:

List<Point> p = new List<Point>();
// add items
p.Distinct(new Comparer());
19
Ilya Smagin

Remplacer Equals (object obj) et GetHashCode () method:

class MyClass
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }
    public int Prop3 { get; set; }

    public override bool Equals(object obj)
    {
        return ((MyClass)obj).Prop2 == Prop2;
    }
    public override int GetHashCode()
    {
        return Prop2.GetHashCode();
    }
}

et ensuite il suffit d'appeler:

List<MyClass> distinctList = someList.Distinct().ToList();
11

Créez une classe qui implémente l'interface IEqualityComparer qui ne vérifie que votre Prop2-Property. Vous pouvez ensuite passer une instance de cette classe à la méthode d'extension Distinct.

2
Christian

Sept. Années. Plus tard.

Je sais que cela faisait longtemps, mais j'avais besoin de la réponse la plus simple et pour le moment (avec .NET 4.5.1), j'ai trouvé ce qui suit comme la réponse la plus simple à laquelle je pouvais arriver:

IEnumerable<long> allIds = waitingFiles.Values.Select(wf => wf.groupId).Distinct();

Ma situation est que j'ai un ConcurrentDictionary qui ressemble à quelque chose comme: ConcurrentDictionary<long, FileModel>

La propriété Valeurs ConcurrentDictionary est fondamentalement mon List<FileModel>.

* FileModel a un groupId qui n'est pas nécessairement unique (bien que, évidemment, la clé (longue) que j'utilise pour ajouter l'objet FileModel au dictionnaire est unique à FileModel).

* Nommé pour plus de clarté dans l'exemple.

Le fait est que j'ai un grand nombre de FileModels (imaginez 100) dans le ConcurrentDictionary et dans ces 100 FileModels, il y a 5 groupIds différents.

À ce stade, j'ai juste besoin d'une liste des identifiants de groupe distincts.

Donc, encore une fois, si j'avais juste une liste de FileModel, le code ressemblerait à ceci:

IEnumerable <long> allIds = allFileModel.Select(fm => fm.groupId).Distinct();
1
raddevus

Utilisez simplement la fonction intégrée DistinctBy de la bibliothèque Microsoft Ajax Utility, comme dans l'exemple ci-dessous:

D'abord y compris la bibliothèque

using Microsoft.Ajax.Utilities;

puis

var distinctList = yourList.DistinctBy(x => x.Prop2).ToList();
0
Anh Hoang