2010-01-24 10 views
8

Ho una classe chiamata Articolo. L'elemento ha una proprietà identificatore chiamata ItemCode che è una stringa. Vorrei ottenere un elenco di tutti gli elementi non distinti in un elenco di elementi.Ottieni elementi non distinti da un oggetto IEnumerable

Esempio:

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

Voglio un elenco contenente gli ultimi due voci

Se uso

var distinctItems = itemsList.Distinct(); 

ottengo l'elenco degli elementi distinti che è grande, ma voglio quasi l'opposto di quello. Potrei sottrarre la distinta lista dalla lista originale ma questo non conterrebbe TUTTE le ripetizioni, ma una sola istanza di ciascuna.

Ho avuto un gioco e non riesco a capire una soluzione elegante. Qualsiasi suggerimento o aiuto sarebbe molto apprezzato. Grazie!

Ho 3.5 in modo LINQ è disponibile

risposta

11

mio prendere:

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

Grazie magnus (e Thomas) e non avrei pensato di utilizzare GroupBy – RichK

2

Si potrebbe desiderare di provare con il gruppo da parte dell'operatore. L'idea sarebbe quella di raggrupparli dal ItemCode e prendendo i gruppi con più di un membro, qualcosa di simile:

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

non riesco a ottenere questo per compilare. Si lamenta delle frasi "group by" e "into" – RichK

+0

Ho dimenticato la "i" tra gruppo e: $ Ora è fissa, ma è essenzialmente la stessa cosa di Magnus ha scritto. –

0

suggerirei a scrivere un metodo di estensione personalizzata, qualcosa di simile:

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; 
      }      
     } 
    } 
} 

È inoltre necessario eseguire l'override metodo Equals() per la classe voce, in modo che gli elementi siano correttamente confrontati con il loro codice.

11

come un metodo di estensione:

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

Pulito e molto riutilizzabile, grazie! – crabCRUSHERclamCOLLECTOR

Problemi correlati