复杂的linq语句-嵌套的组/位置/总和/选择

时间:2019-11-08 13:56:48

标签: c# linq

我有一个对象,例如下面的示例

object = {
        [0] {Name: "Foo", Customer: "Alex", Number: "33.2", Amt: 100.50, FileId: 12345611, FileNumber: "0987-123"}
        [1] {Name: "Bar", Customer: "Josh" Number: "1", Amt: 100.50, FileId: 456546456, FileNumber: "0987-123"}
        [2] {Name: "Foo", Customer: "Alex", Number: "33.2", Amt: 110.00, FileId: 12345611, FileNumber: "0987-123"}
        [3] {Name: "Foo", Customer: "Frank", Number: "9.8", Amt: 100.50, FileId: 324234, FileNumber: "9999-123"}
        [4] {Name: "Test2", Customer: "Bob" , Number: "1.9", Amt: 100.50, FileId: 782724, FileNumber: "0987-123"}
        [5] {Name: "Foo", Customer: "Alex" , Number: "33.2", Amt: 50.80, FileId: 9872561, FileNumber: "8181-1273"}
    }

我需要它看起来像下面的

groupedObject = {
        [0] {Name: "Foo", 
                Rows: {
                        row: {
                            [0] {Number: "33.2", Customer: "Alex", Details: {
                                        [0] {Amt: 210.50, Number: "33.2", FileId: 12345611, FileNumber: "0987-123"}
                                        [0] {Amt: 50.80, Number: "33.2", FileId: 9872561, FileNumber: "8181-1273"}
                                    }
                                }
                            [1] {Number: "9.8", Customer: "Frank", Details: {
                                        [0] {Amt: 100.50, Number: "9.8", FileId: 324234, FileNumber: "9999-123"}
                                    }
                                }
                        }
                    }
            }
        [1] {Name: "Bar", 
                Rows: {
                        row: {
                            [0] {Number: "33.2", Customer: "Josh", Details: {
                                        [0] {Amt: 100.50, Number: "1", FileId: 456546456, FileNumber: "0987-123"}
                                    }
                                }
                        }
                    }
            }
        [2] {Name: "Test2", 
                Rows: {
                        row: {
                            [0] {Number: "1.9", Customer: "Bob", Details: {
                                        [0] {Amt: 100.50, Number: "1.9", FileId: 782724, FileNumber: "0987-123"}
                                    }
                                }
                        }
                    }
            }
    }   

我要完成的工作是按名称分组,然后按名称在名称中分组,然后在该客户中的客户详细信息以及具有相同fileID的详细信息需要合并行。 linq有可能吗?

如果需要可视化,下面是我需要的,但是使用XML。

<main>
    <UniqueNames>
        <randominfo>true</randominfo>
        <randominfo2>false</randominfo2>
        <head>
            <Name>Foo</Name>
        </head>
        <rows>
            <row>
                <Number>"33.2"</Number>
                <Customer>"Alex"</Customer>
                <Details>
                    <Detail>
                        <Amt>210.50</Amt>
                        <Number>"33.2"</Number>
                        <FileId>12345611</FileId>
                        <FileNumber>"0987-123"</FileNumber>
                    </Detail>
                    <Detail>
                        <Amt>50.80</Amt>
                        <Number>"33.2"</Number>
                        <FileId>9872561</FileId>
                        <FileNumber>"8181-1273"</FileNumber>
                    </Detail>
                </Details>
            </row>
        </rows>
    </UniqueNames>
    <UniqueNames>
        <randominfo>true</randominfo>
        <randominfo2>false</randominfo2>
        <head>
            <Name>Bar</Name>
        </head>
        <rows>
            <row>
                <Number>"33.2"</Number>
                <Customer>"Josh"</Customer>
                <Details>
                    <Detail>
                        <Amt>100.50</Amt>
                        <Number>"1"</Number>
                        <FileId>456546456</FileId>
                        <FileNumber>"0987-123"</FileNumber>
                    </Detail>
                </Details>
            </row>
        </rows>
    </UniqueNames>
    <UniqueNames>
        <randominfo>true</randominfo>
        <randominfo2>false</randominfo2>
        <head>
            <Name>Test2</Name>
        </head>
        <rows>
            <row>
                <Number>"1.9"</Number>
                <Customer>"Bob"</Customer>
                <Details>
                    <Detail>
                        <Amt>100.50</Amt>
                        <Number>"1.9"</Number>
                        <FileId>782724</FileId>
                        <FileNumber>"0987-123"</FileNumber>
                    </Detail>
                </Details>
            </row>
        </rows>
    </UniqueNames>
</main>

我尝试了以下方法... 按名称对我的对象进行分组,然后为每个名称列出每个对象。

var testgroup = TestObject.GroupBy( item => item.Name)
    .Select(group => new { Name = group.Key, Items = group.ToList() })
    .ToList()

然后我还有另一个用于获取所有详细信息

var Details =
                (from c in TestObject
                    group c by new
                    {
                        c.Number,
                        c.FileId,
                        c.FileNumber,
                    } into cFIDs
                    select new FileAllocation()
                    {

                        FileAmount = cFIDs.Sum(s => s.Amt),
                        Number = cFIDs.Key.Number,
                        FileId = cFIDs.Key.FileId,
                        FileNumber = cFIDs.Key.FileNumber,
                    }).ToList();

以上内容使我可以分组并生成所需的详细信息,并且第一个按名称分组并列出每个行的详细信息...我也尝试了以下操作。

我只是不确定如何将它们放在一起

1 个答案:

答案 0 :(得分:1)

您需要3个独立的GroupBy语句,然后将每个语句投影到输出的正确属性。有几种方法可以实现,但可能最容易阅读的是这样的:

var result = inputs.GroupBy(x => x.Name)
        .Select(g => new {
            Name = g.Key,
            Rows = g.GroupBy(x => new {x.Customer, x.Number})
                .Select(g2 => new{
                    Number = g2.Key.Number,
                    Customer = g2.Key.Customer,
                    Details = g2.GroupBy(x => new {x.FileId,x.FileNumber})
                                .Select(g3 => new {Amt = g3.Sum(x => x.Amt), g2.Key.Number, g3.Key.FileId, g3.Key.FileNumber})

                })
        });

以下是一个实时工作示例,其中包含您的数据:https://dotnetfiddle.net/ozcWUM

以上使用匿名对象,您可以根据需要轻松地投影到自定义对象。例如,最后的投影显示为:

...
.Select(g3 => new FileAllocation{Amt = g3.Sum(x => x.Amt), g2.Key.Number, g3.Key.FileId, g3.Key.FileNumber})
...