2010-10-08 9 views
1

Je regroupe plusieurs listes dans une liste et je voudrais la rendre distincte en fonction de l'une des propriétés de Foo (Foo.Prop1) .. Je n'ai pas accès à modifier Foo's Égalité de comparaison.Question de requête Linq: Distinct basé sur la propriété de l'objet

Dictionary<string, List<Foo>> fooDictionary = new Dictionary<string, List<Foo>>(); 
List<Foo> foovals = (from e in fooDictionary 
        where e.Key == "foo1" || e.Key == "foo2" || e.Key == "foo3" 
        select e.Value).SelectMany(f => f).ToList(); 

la seule chose qui manque ici est le .Distinct() à la fin, de faire cependant, unique, de Foo dans mon cas, je ne peux rien modifier au sujet de Foo, afin d'appeler simplement Distinct() NUL travail.

Existe-t-il un moyen de modifier cette requête pour renvoyer des éléments Distinct basé sur Foo.Prop1?

Répondre

2

Vous pouvez utiliser la méthode DistinctBy dans MoreLINQ :

var query = fooVals.DistinctBy(foo => foo.Property1); 
+0

sympa! Bien que cela soit à l'intérieur d'un template CodeSmith, je ne sais pas si je peux ajouter des extensions de langue. –

3

Vous pouvez passer un comparateur d'égalité personnalisée à Distinct():

.SelectMany().Distinct(new FooEqualityComparer()); 

Dans un nouveau fichier, "FooEqualityComparer.cs":

public class FooEqualityComparer : IEqualityComparer<Foo> 
{ 
    public bool Equals(Foo x, Foo y) 
    { 
     return Equals(x.Prop1, y.Prop1); 
    } 

    public int GetHashCode(Foo x) 
    { 
     return x.Prop1.GetHashCode(); 
    } 
} 
+0

aussi, ne peut pas vraiment faire cela .. c'est dans un modèle de code, et Foo est généré dynamiquement par le schéma XML, donc pas même accessible dans un modèle de code .. au moins que je sais comment .. –

+0

Vous ne savez pas besoin d'accéder au code de classe pour écrire un comparateur d'égalité ... – codekaizen

+0

Je le fais, parce que Foo est une classe personnalisée, et le comparateur d'égalité devra être conscient de quelles propriétés il doit les comparer –

0
var tempKeys = new HashSet<int>(); // change int to the actual type of Prop1 

List<Foo> foovals = (from e in fooDictionary 
        where e.Key == "foo1" || e.Key == "foo2" || e.Key == "foo3" 
        select e.Value).SelectMany(f => f) 
            .Where(f => tempKeys.Add(f.Prop1)) 
            .ToList(); 
+0

Trop "intelligent" et illisible. Et hacky: «Où» avec des effets secondaires, beurk. – Timwi

+0

@Timwi: C'est juste une preuve de concept, et c'est à peu près ce que 'Distinct' fait lui-même dans les coulisses. Enveloppez-le dans une méthode d'extension générale qui accepte également une fonction de sélection de clé et vous venez de réécrire 'DistinctBy', comme mentionné dans la réponse de Jon. – LukeH