2010-01-24 61 views
8

我有一个名为Item的类。 Item有一个称为ItemCode的标识属性,它是一个字符串。我想要列出项目列表中所有非独特项目的列表。从IEnumerable获取不同元素

例子:

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

我想包含底部两个条目

如果我使用

var distinctItems = itemsList.Distinct(); 

我得到不同的项目清单,这是伟大的清单,但我想几乎与此相反。我可以从原始列表中减去不同的列表,但不包含所有重复,只是每个列表的一个实例。

我玩过一个游戏,找不到优雅的解决方案。任何指针或帮助将不胜感激。谢谢!

我有这么3.5 LINQ提供

回答

11

我的看法:

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

感谢magnus(和Thomas),我不会想到用GroupBy – RichK 2010-01-24 15:32:06

2

你可能想通过操作员组来试试吧。这个想法是将它们分组由ItemCode,走组与多个成员,是这样的:

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

我不能得到这个编译。它呻吟着'group by'和'into'语句 – RichK 2010-01-24 15:31:12

+0

我忘记了group和by之间的“i”:$现在它已经修复了,但它基本上与magnus写的一样。 – 2010-01-24 16:21:35

0

我建议编写自定义扩展方法,如下所示:

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

您还需要为您的Item类重写Equals()方法,以便通过它们的代码正确比较项目。

11

作为一个扩展方法:

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

干净且非常可重用,谢谢! – crabCRUSHERclamCOLLECTOR 2017-02-21 16:56:35