Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I group by a list of elements?

I run into this issue again and again: how can I group a list of objects by a containing list of other objects?

I have a list of objects of type A and each of these objects has an property (lets call it ListProp) which is a list also. ListProp has elements of the type B. There are multiple elements of type A with identically B-objects in ListProp, but the ListProp property reference differs from element to element. How can I group these A-objects the fastest way, where the B-objects in ListProp are identically?

Sample code:

class Program
{
    static void Main(string[] args)
    {
        var exampleList = new List<A>
        {
            // Should be in first group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in first group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in second group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 1 }},
                new B { Prop = new C { Number = 1 }}
            }},
            // Should be in third group
            new A { ListProp = new List<B>
            {
                new B { Prop = new C { Number = 0 }},
                new B { Prop = new C { Number = 0 }}
            }}
        };

        // Doesn't work because the reference of ListProp is always different
        var groupedExampleList = exampleList.GroupBy(x => x.ListProp);
    }
}

class C
{
    public int Number { get; set; }
    public override bool Equals(object o)
    {
        if (o is C)
            return Number.Equals(((C)o).Number);
        else
            return false;
    }
}

class B
{
    public C Prop { get; set; }
}

class A
{
    public IList<B> ListProp { get; set; }
}
like image 578
germanSharper Avatar asked Apr 20 '12 11:04

germanSharper


People also ask

How do you Groupby a list in Python?

You can use itertools. groupby() to handle not only lists but also tuples, strings, etc. Use tuple() if you want to make a group a tuple instead of a list. Use join() if you want to make a group into a string.

How do you group similar values in a list in Python?

Method #1 : Using lambda + itertools.groupby() + split() The combination of above three functions help us achieve the task. The split method is key as it defines the separator by which grouping has to be performed. The groupby function does the grouping of elements.

How many elements can be passed to a list?

1) Yes, list can store 100000+ elements.


2 Answers

You can implement IEqualityComparer<List<B>> and use it in the other GroupBy overload.

public class ListOfBEqualityComparer : IEqualityComparer<List<B>>
{
    public bool Equals(List<B> x, List<B> y)
    {
        // you can also implement IEqualityComparer<B> and use the overload
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<B> obj)
    {
        //implementation of List<T> may not work for your situation
        return obj.GetHashCode();
    }
}

Then you can use the overload

var groupedExampleList = exampleList.GroupBy(x => x.ListProp, 
                                             new ListOfBEqualityComparer());
like image 194
Ufuk Hacıoğulları Avatar answered Sep 20 '22 09:09

Ufuk Hacıoğulları


Try this:

GroupBy(x => String.Join(",", x.ListProp));

It will group by 0,1; 0,1; 0,1; 0,1,1; 0,1 accordingly.

like image 37
abatishchev Avatar answered Sep 21 '22 09:09

abatishchev