2010-01-24 1 views
8

Mam klasę o nazwie Item. Element ma właściwość identyfikatora o nazwie ItemCode, który jest łańcuchem. Chciałbym uzyskać listę wszystkich nierozróżnialnych elementów na liście przedmiotów.Uzyskaj elementy nieodróżnialne od IEnumerable

Przykład:

List<Item> itemList = new List<Item>() 
{ 
    new Item("code1", "description1"), 
    new Item("code2", "description2"), 
    new Item("code2", "description3"), 
}; 

Chcę listę zawierającą dolne dwa wpisy

Jeśli używam

var distinctItems = itemsList.Distinct(); 

uzyskać listę różnych przedmiotów, który jest wielki, ale chcę wręcz przeciwnie. Mógłbym odjąć odrębną listę od pierwotnej listy, ale nie zawierałoby to WSZYSTKICH powtórzeń, po prostu po jednej instancji.

Mam grę i nie mogę wymyślić eleganckiego rozwiązania. Wszelkie wskazówki i pomoc będą mile widziane. Dzięki!

mam 3.5 tak LINQ jest dostępny

Odpowiedz

11

My się:

var distinctItems = 
    from list in itemsList 
    group list by list.ItemCode into grouped 
    where grouped.Count() > 1 
    select grouped; 
+0

Dzięki magnus (i Thomas) i nie pomyślałem by użyć GroupBy – RichK

2

Można spróbować go z grupy przez operatora. Pomysł byłoby grupie nich przez ItemCode i biorąc grupy z więcej niż jednego członka, coś jak:

var grouped = from i in itemList 
       group i by i.ItemCode into g 
       select new { Code = g.Key, Items = g }; 

var result = from g in grouped 
      where g.Items.Count() > 1; 
+0

nie mogę tego skompilować. Jęczą o stwierdzeniach "grupa po" i "w" – RichK

+0

Zapomniałem "i" między grupą a przez: $ Teraz jest naprawione, ale to w istocie to samo, co napisał magnus. –

0

Sugeruję pisanie niestandardową metodę rozszerzenia, coś takiego:

static class RepeatedExtension 
{ 
    public static IEnumerable<T> Repeated<T>(this IEnumerable<T> source) 
    { 
     var distinct = new Dictionary<T, int>(); 
     foreach (var item in source) 
     { 
      if (!distinct.ContainsKey(item)) 
       distinct.Add(item, 1); 
      else 
      { 
       if (distinct[item]++ == 1) // only yield items on first repeated occurence 
        yield return item; 
      }      
     } 
    } 
} 

Należy również zastąpić equals() metodę klasy towaru, dzięki czemu elementy są prawidłowo porównaniu ich kodu.

11

jako metodę rozszerzenia:

public static IEnumerable<T> NonDistinct<T, TKey> (this IEnumerable<T> source, Func<T, TKey> keySelector) 
{ 
    return source.GroupBy(keySelector).Where(g => g.Count() > 1).SelectMany(r => r); 
} 
+0

Czyste i bardzo wielokrotnego użytku, dzięki! – crabCRUSHERclamCOLLECTOR