如何编写自定义Linq groupBy

时间:2016-05-20 14:44:52

标签: c# linq group-by

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

如何编写groupBy比较器?我想要CoordSys平等的团体。这是我第一次尝试编写自定义groupBy。这个示例代码在尝试简化时有很多注意事项。实际的CoordSys更复杂。

3 个答案:

答案 0 :(得分:3)

您可以将views分组为

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

这会为您提供IEnumerable<IGrouping<View>>。你可以这样使用它,例如:

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

IGrouping必须是组中IEnumerable的{​​{1}}加上View属性,表示您按Key分组的值情况)。

答案 1 :(得分:1)

试试这个

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

答案 2 :(得分:0)

这样做的目的是帮助我了解如何编写自定义比较器。虽然简单的GrouBy可以解决我的样本,但最终的解决方案使用了一些需要自定义比较器的API调用。无论如何,我有一个现在有效的样本。

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