DustyB
DustyB

Reputation: 185

how to write custom Linq groupBy

    class Program
{
    static void Main(string[] args)
    {
        IEnumerable<View> views = new List<View>
        {
            new View() {CoordSys = new Plane(){Org=new Origin(){x=1,Vector=0}}, PartNums = new List<int> {1,2,3}}
            ,new View() {CoordSys = new Plane(){Org=new Origin(){x=2,Vector=0}}, PartNums = new List<int> {4,5,6}}
            ,new View() {CoordSys = new Plane(){Org=new Origin(){x=3,Vector=0}}, PartNums = new List<int> {13,14,15}}
            ,new View() {CoordSys = new Plane(){Org=new Origin(){x=2,Vector=0}}, PartNums = new List<int> {7,8,9}}
            ,new View() {CoordSys = new Plane(){Org=new Origin(){x=2,Vector=0}}, PartNums = new List<int> {10,11,12}}
            ,new View() {CoordSys = new Plane(){Org=new Origin(){x=1,Vector=0}}, PartNums = new List<int> {16,17,18}}
        };

        IEnumerable<View> viewsByGroup = views.GroupBy(v => v, new ViewComparer());

        // loop to process groups

        Console.ReadLine();
    }
}

class ViewComparer : IEqualityComparer<View>
{
    public bool Equals(View x, View y)
    {
        return x.CoordSys.Org.x == y.CoordSys.Org.x
            && x.CoordSys.Org.Vector == y.CoordSys.Org.Vector;
    }

    public int GetHashCode(View obj)
    {
        return obj.CoordSys.GetHashCode();
    }
}

How do I write the groupBy comparer? I want groups where CoordSys is equal. This is my first attempt to write a custom groupBy. This sample code has a lot of ints in trying to make it simple. The actual CoordSys is more complex.

Upvotes: 0

Views: 104

Answers (3)

DustyB
DustyB

Reputation: 185

The purpose of this was to help me understand how to write a custom comparer. Although a simple GrouBy would have solved my sample, the final solution utilized some API calls that required a custom comparer. Anyway I have a sample that now works.

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<View> views = new List<View>
        {
            new View() {CoordSys = new Plane(){Origin=new Origin(){x=1,y=0},Vector=0}, PartNums = new List<int> {1,2,3}}
            ,new View() {CoordSys = new Plane(){Origin=new Origin(){x=3,y=0},Vector=0}, PartNums = new List<int> {13,14,15}}
            ,new View() {CoordSys = new Plane(){Origin=new Origin(){x=2,y=0},Vector=0}, PartNums = new List<int> {4,5,6}}
            ,new View() {CoordSys = new Plane(){Origin=new Origin(){x=1,y=0},Vector=0}, PartNums = new List<int> {16,17,18}}
            ,new View() {CoordSys = new Plane(){Origin=new Origin(){x=2,y=0},Vector=0}, PartNums = new List<int> {7,8,9}}
            ,new View() {CoordSys = new Plane(){Origin=new Origin(){x=2,y=0},Vector=0}, PartNums = new List<int> {10,11,12}}
        };

        var viewsByGroup = views.GroupBy(p => p, new ViewComparer());

        foreach (var group in viewsByGroup)
        {
            foreach (var numList in group.Select(p => p.PartNums))
                foreach (int num in numList)
                    Console.Write(num + ", ");

            Console.WriteLine();
        }

        Console.ReadLine();
    }
}

class ViewComparer : IEqualityComparer<View>
{
    public bool Equals(View x, View y)
    {
        return x.CoordSys.Origin.x == y.CoordSys.Origin.x
            && x.CoordSys.Vector == y.CoordSys.Vector;
    }

    public int GetHashCode(View obj)
    {
        return obj.CoordSys.Origin.x.GetHashCode()
            ^ obj.CoordSys.Vector.GetHashCode();
    }
}

Upvotes: 0

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43906

You can group your views like this

var groups = views.GroupBy(v => v.CoordSys);

This gives you an IEnumerable<IGrouping<View>>. You can use this for example like this:

foreach(var group in groups)
{
    Console.Write("CoordSys = " + group.Key + " ");
    Console.Write("Elements: " + group.Count());
}

The IGrouping is essentialy an IEnumerable of the Views in the group plus a Key property representing the value you grouped by (CoordSys in your case).

Upvotes: 3

Kahbazi
Kahbazi

Reputation: 15015

try this

var Group = views.GroupBy(v => v.CoordSys);

Upvotes: 1

Related Questions