使用 Linq to Object 进行 GroupBy

发布于 2024-11-28 17:36:52 字数 1827 浏览 1 评论 0原文

我正在为 Linq 的 GroupBy 苦苦挣扎。我想我无法用一种表达方式做到这一点,但不知道如何解决这个问题。

我有以下 2 个类:

public class Shipment {
  public string PortOfOrigin{get;set;}
  public string PortOfDestination{get;set;}
  public ICollection<Invoice> Invoices{get;set;}
}

public class Invoice{
  public string InvoicePeriod {get;set;}
  public decimal Amount {get;set;}
}

我有一组发货,所有发货都有一组发票。这是一个例子。

List<Shipment> shipments = new List<Shipment>
{
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 1000},
            new Invoice{InvoicePeriod = "201106", Amount = 2000},
            new Invoice{InvoicePeriod = "201107", Amount = 1000}
        }
    },
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000},
            new Invoice{InvoicePeriod = "201107", Amount = 2000}
        }
    },
    new Shipment { PortOfOrigin = "USDAL", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000}
        }
    }
};

现在我想按以下内容进行分组:

Shipment.PortOfOrigin、Shipment.PortOfDestionation、Shipment.Invoices.InvoicePeriod。

所以我想要这样的结果

PortOfOrigin    PortOfDestination   InvoicePeriod   Amount
------------------------------------------------------------------------
USLOS           UKLON               201106          6000
USLOS           UKLON               201107          3000
USDAL           UKLON               201106          3000

是否可以在 Invoices.InvoicePeriod 上进行分组?

I am strugling with a GroupBy for Linq. I guess I can't do it in one expression but have no clue how to solve the problem.

I have the following 2 classes:

public class Shipment {
  public string PortOfOrigin{get;set;}
  public string PortOfDestination{get;set;}
  public ICollection<Invoice> Invoices{get;set;}
}

public class Invoice{
  public string InvoicePeriod {get;set;}
  public decimal Amount {get;set;}
}

I have a collection of Shipments that all have a collection of Invoice. Here is an example.

List<Shipment> shipments = new List<Shipment>
{
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 1000},
            new Invoice{InvoicePeriod = "201106", Amount = 2000},
            new Invoice{InvoicePeriod = "201107", Amount = 1000}
        }
    },
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000},
            new Invoice{InvoicePeriod = "201107", Amount = 2000}
        }
    },
    new Shipment { PortOfOrigin = "USDAL", PortOfDestionation = "UKLON", 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000}
        }
    }
};

Now I want to group by the following:

Shipment.PortOfOrigin, Shipment.PortOfDestionation, Shipment.Invoices.InvoicePeriod.

So I want the result like this

PortOfOrigin    PortOfDestination   InvoicePeriod   Amount
------------------------------------------------------------------------
USLOS           UKLON               201106          6000
USLOS           UKLON               201107          3000
USDAL           UKLON               201106          3000

Is this even possible to do a group like this where I want to group on the Invoices.InvoicePeriod?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云醉月微眠 2024-12-05 17:36:52

更新:我已更新我的答案以包含发货数量。这要求货件具有 ID 字段。


下面的代码可以解决这个问题:

//first flatten the data so it's easier to manipulate
var query = from s in shipments
            from i in s.Invoices
            select new
            {
                s.ShipmentUniqueIdentifier,
                s.PortOfOrigin,
                s.PortOfDestination,
                i.InvoicePeriod,
                i.Amount
            };

//group the data as desired
var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod });

//finally sum the amounts
var results = from g in grouping
              select new
              {
                  g.Key.PortOfOrigin,
                  g.Key.PortOfDestination,
                  g.Key.InvoicePeriod,
                  Amount = g.Select(s => s.Amount).Sum(),
                  NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count()
              };

这是输出:

在此处输入图像描述

更新: 正如所承诺的,这是一个完整的工作示例:

public class Shipment {
  public Guid ShipmentUniqueIdentifier{get;set;}
  public string PortOfOrigin{get;set;}
  public string PortOfDestination{get;set;}
  public ICollection<Invoice> Invoices{get;set;}
}

public class Invoice {
  public string InvoicePeriod {get;set;}
  public decimal Amount {get;set;}
}

List<Shipment> shipments = new List<Shipment>
{
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(),
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 1000},
            new Invoice{InvoicePeriod = "201106", Amount = 2000},
            new Invoice{InvoicePeriod = "201107", Amount = 1000}
        }
    },
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(),
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000},
            new Invoice{InvoicePeriod = "201107", Amount = 2000}
        }
    },
    new Shipment { PortOfOrigin = "USDAL", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000}
        }
    }
};

void Main()
{
    //first flatten the data so it's easier to manipulate
    var query = from s in shipments
                from i in s.Invoices
                select new
                {
                    s.ShipmentUniqueIdentifier,
                    s.PortOfOrigin,
                    s.PortOfDestination,
                    i.InvoicePeriod,
                    i.Amount
                };

    //group the data as desired
    var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod });

    //finally sum the amounts
    var results = from g in grouping
                  select new
                  {
                      g.Key.PortOfOrigin,
                      g.Key.PortOfDestination,
                      g.Key.InvoicePeriod,
                      Amount = g.Select(s => s.Amount).Sum(),
                      NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count()
                  };

    //output the results
    results.Dump();
}

UPDATE: I've updated my answer to include the number of Shipments. This requires the shipment to have an ID field.


The following will do the trick:

//first flatten the data so it's easier to manipulate
var query = from s in shipments
            from i in s.Invoices
            select new
            {
                s.ShipmentUniqueIdentifier,
                s.PortOfOrigin,
                s.PortOfDestination,
                i.InvoicePeriod,
                i.Amount
            };

//group the data as desired
var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod });

//finally sum the amounts
var results = from g in grouping
              select new
              {
                  g.Key.PortOfOrigin,
                  g.Key.PortOfDestination,
                  g.Key.InvoicePeriod,
                  Amount = g.Select(s => s.Amount).Sum(),
                  NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count()
              };

Here's the output:

enter image description here

UPDATE: As promised, here's a complete working example:

public class Shipment {
  public Guid ShipmentUniqueIdentifier{get;set;}
  public string PortOfOrigin{get;set;}
  public string PortOfDestination{get;set;}
  public ICollection<Invoice> Invoices{get;set;}
}

public class Invoice {
  public string InvoicePeriod {get;set;}
  public decimal Amount {get;set;}
}

List<Shipment> shipments = new List<Shipment>
{
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(),
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 1000},
            new Invoice{InvoicePeriod = "201106", Amount = 2000},
            new Invoice{InvoicePeriod = "201107", Amount = 1000}
        }
    },
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(),
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000},
            new Invoice{InvoicePeriod = "201107", Amount = 2000}
        }
    },
    new Shipment { PortOfOrigin = "USDAL", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
        Invoices = new List<Invoice>
        {
            new Invoice{InvoicePeriod = "201106", Amount = 3000}
        }
    }
};

void Main()
{
    //first flatten the data so it's easier to manipulate
    var query = from s in shipments
                from i in s.Invoices
                select new
                {
                    s.ShipmentUniqueIdentifier,
                    s.PortOfOrigin,
                    s.PortOfDestination,
                    i.InvoicePeriod,
                    i.Amount
                };

    //group the data as desired
    var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod });

    //finally sum the amounts
    var results = from g in grouping
                  select new
                  {
                      g.Key.PortOfOrigin,
                      g.Key.PortOfDestination,
                      g.Key.InvoicePeriod,
                      Amount = g.Select(s => s.Amount).Sum(),
                      NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count()
                  };

    //output the results
    results.Dump();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文