2010-01-17 4 views
8

Можно ли получить отдельные элементы List на основе свойств объектов в List?Linq Distinct на основе свойства объекта

как коснуться: Distinct(x => x.id)

Что не полезно для меня заключается в следующем: .Select(x => x.id).Distinct(), потому что тогда я хотел бы получить обратно List<int> вместо List<MyClass>

+0

Почти такие же, как: http://stackoverflow.com/questions/520030/why-is-there-no-linq-method-to-return-distinct-values-by-a-predicate –

ответ

2

Вам нужно DistinctBy. Это не часть стандартных .NET-библиотек, но Jon Skeet внедрил реализацию Linq для объектов here. Он также включен в morelinq.

6

Это звучит как группирование построить для меня, потому что вы должны решить, какой из предположительно идентичных объекта, который вы на самом деле хотите, чтобы вернуть

var q = from x in foo 
     group x by x.Id into g 
     select g.First(); // or some other selection from g 

Просто потому, что Id является идентичным по нескольким позициям, не означает, что элементы идентичны для других свойств, поэтому вам нужно явно решить, какой элемент будет возвращен.

5

Что вы можете сделать, это реализовать свой собственный IEqualityComparer<T> и передать в Distinct:

class SomeType { 
    public int id { get; set; } 
    // other properties 
} 
class EqualityComparer : IEqualityComparer<SomeType> { 
    public bool Equals(SomeType x, SomeType y) { 
     return x.id == y.id; 
    } 

    public int GetHashCode(SomeType obj) { 
     return obj.id.GetHashCode(); 
    } 
} 

Тогда:

// elements is IEnumerable<SomeType> 
var distinct = elements.Distinct(new EqualityComparer()); 
// distinct is IEnumerable<SomeType> and contains distinct items from elements 
// as per EqualityComparer 
2

Существует перегрузка на Enumerable.Distinct(), который принимает IEqualityComparer.

Вот пример, где я использовал его для фильтрации целых чисел по четности:

class IntParitiyComparer : IEqualityComparer<int> 
    { 
     public bool Equals(int x, int y) 
     { 
      return x % 2 == y % 2; 
     } 

     public int GetHashCode(int obj) 
     { 
      return obj % 2; 
     } 
    } 

    static void Main(string[] args) 
    { 
     var x = new int[] { 1, 2, 3, 4 }.Distinct(new IntParitiyComparer()); 

     foreach (var y in x) Console.WriteLine(y); 
    } 

Это неуклюжее; DistinctBy будет чище.