2010-02-14 12 views
8

Próbuję uzyskać odrębną listę słów z tablicy słów z następującego kodu:Wybierz odrębną listę słów z tablicy z LINQ

string words = "this is a this b"; 

var split = words.Split(' '); 

IEnumerable<Word> distinctWords = (from w in split 
          select new Word 
            { 
             Text = w.ToString() 
            } 
         ).Distinct().ToList(); 

myślałem, że to byłoby wyjąć podwójne występowanie "this", ale zwraca listę każdego słowa w wyrażeniu.

Czy ktoś może zasugerować, w jaki sposób mogę uzyskać wyraźną listę? Dzięki

Dave

+0

nie powinno być 2. linia 'string [] Podział = słowa. Split() '? –

+0

D'Oh! - @Mark, masz rację. Sądzę, że trochę się rozlazłem z moim kopiowaniem/wklejeniem - naprawiłem to teraz. Na tym etapie miałem jednak jedną lub dwie szklanki! :-) – DaveDev

Odpowiedz

19

W przykładzie, każdy obiekt Słowo jest odrębne, ponieważ nie ma porównania, który patrzy na właściwości Text.

Jednak nie ma powodu, aby utworzyć nowy obiekt:

var distinctWords = (from w in split 
         select w).Distinct().ToList(); 

Albo prościej:

var distinctWords = new List<string>(split.Distinct()); 
1

Nie napisali kod dla klasy Word, ale domyślam się, że nie realizuje Equals z porównania wartości więc masz realizację domyślnej Equals który właśnie sprawdza obiekt referencje. Pamiętaj, że jeśli zdecydujesz się na wdrożenie własnej wersji Equals, musisz poprawnie wdrożyć GetHashCode.

Alternatywnym sposobem rozwiązania tego problemu jest podanie IEqualityComparer jako parametru funkcji Distinct.

1

Problem polega na tym, że tworzy się kilka obiektów programu Word, które zawierają tę samą wartość, ale jak kompilator powinien wiedzieć, że będą to te same elementy?

Spróbuj

(from w in split.Distinct() 
select new Word { Text = w.ToString()}).ToList(); 
0

Jak inni zauważyć, problem jest zapewne, że obiekt Word nie implementuje strukturalny równość (porównaj aktualną zawartość, a nie referencje instancji). Jeśli nadal chcesz otrzymać kolekcję Word obiektów jak wynik, ale używać Distinct bazowych wartości ciągów, można napisać to:

IEnumerable<Word> distinctWords = 
    (from w in split.Distinct() 
    select new Word { Text = w.ToString() }).ToList();