使用Linq到对象的GroupBy

问题描述 投票:1回答:1

我正在为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上分组的地方进行这样的分组?

c# group-by linq-to-objects
1个回答
1
投票

UPDATE:我已经更新了答案,以包括发货数量。这要求货件具有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()
              };

这是输出:

“在此处输入图像描述”

UPDATE:如所保证的,这是一个完整的工作示例:

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();
}
© www.soinside.com 2019 - 2024. All rights reserved.