开发者

Get Non-Distinct elements from an IEnumerable

I have a class called Item. Item has an identif开发者_StackOverflow中文版ier property called ItemCode which is a string. I would like to get a list of all non-distinct Items in a list of Items.

Example:

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

I want a list containing the bottom two entries

If I use

var distinctItems = itemsList.Distinct();

I get the list of distinct items which is great, but I want almost the opposite of that. I could subtract the the distinct list from the original list but that wouldn't contain ALL repeats, just one instance of each.

I've had a play and can't figure out an elegant solution. Any pointers or help would be much appreciated. Thanks!

I have 3.5 so LINQ is available


My take:

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


as an extension method:

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


You might want to try it with group by operator. The idea would be to group them by the ItemCode and taking the groups with more than one member, something like :

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;


I'd suggest writing a custom extension method, something like this:

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

You also need to override Equals() method for your Item class, so that items are correctly compared by their code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜