仅当其中一个字段是特定值时,LINQ才会对多个字段进行分组

时间:2017-05-11 12:51:55

标签: c# wpf linq

我正在尝试按2个字段(类别,然后是供应商)对列表进行分组,但是值不同。如果类别为“01”,则将所有成本加起来。如果类别不是“01”,则按类别分组,然后按供应商分组。

一些演示数据:

List<MyItem> myItemList = new List<MyItem>();
myItemList.Add(new MyItem{Vendor="Ven1", Cost=100, Category="01"});
myItemList.Add(new MyItem{Vendor="Ven2", Cost=10, Category="02"});
myItemList.Add(new MyItem{Vendor="Ven3", Cost=50, Category="02"}));
myItemList.Add(new MyItem{Vendor="Ven2", Cost=40, Category="01"});
myItemList.Add(new MyItem{Vendor="Ven2", Cost=20, Category="01"});
myItemList.Add(new MyItem{Vendor="Ven3", Cost=30, Category="02"});
myItemList.Add(new MyItem{Vendor="Ven1", Cost=10, Category="03"});

我目前正在做的事情:

List<MyItem> groupedItems = myItemList.GroupBy(a=> new {a.Category, a.Vendor})
                                      .Select(b=> new MyItem{
                                            Vendor = b.First().Vendor,
                                            Cost = b.Sum(c => c.Cost),
                                            Category = b.First().Category
                                       }).ToList();

我想做什么(也就是我最好的猜测):

List<MyItem> groupedItems = myItemList.GroupBy(a=> new {a.Category.Where(z=>z.Category.Equals("01:)), a.Vendor})
                                      .Select(b=> new MyItem{
                                            Vendor = b.First().Vendor,
                                            Cost = b.Sum(c => c.Cost),
                                            Category = b.First().Category
                                       }).ToList();

期望的结果:

Category = "01", Vendor = "N/A ", Cost = 160
Category = "02", Vendor = "Ven2", Cost = 10
Category = "02", Vendor = "Ven3", Cost = 80
Category = "03", Vendor = "Ven1", Cost = 10

3 个答案:

答案 0 :(得分:4)

GroupBy返回一个包含2个字段的匿名类型。返回对象内的值可以是任何值。在这种情况下,如果类别为&#34; 01&#34;:myItemList.GroupBy(a=> new {a.Category, Vendor= a.Category == "01" ? null : a.Vendor})可以更改它们为了与当前代码保持一致,该属性名为Vendor,但可以是任何名称。

在您当前的代码中:

List<MyItem> groupedItems = myItemList
    .GroupBy(a => new {a.Category, Vendor = a.Category == "01" ? null : a.Vendor})
    .Select(b => new MyItem
    {
        Vendor = b.First().Vendor,
        Cost = b.Sum(c => c.Cost),
        Category = b.First().Category
    })
    .ToList();

或稍微改动,而不是组的First()值,您可以重复使用密钥(并一次性实施N\A

List<MyItem> groupedItems = myItemList
      .GroupBy(a=> new {a.Category, Vendor= a.Category == "01" ? "N/A" : a.Vendor})
      .Select(b=> new MyItem{
            Vendor = b.Key.Vendor,
            Cost = b.Sum(c => c.Cost),
            Category = b.Key.Category
       }).ToList();

答案 1 :(得分:0)

暂时我想创建两个单独的查询:

List<MyItem> groupedItemsByCat01 = myItemList.Where(z => z.Category.Equals("01"))
                                             .GroupBy(a => a.Category)
                                             .Select(b=> new MyItem{
                                                Vendor = "N/A",
                                                Cost = b.Sum(c => c.Cost),
                                                Category = b.First().Category
                                           }).ToList();

List<MyItem> groupedItemsByOther = myItemList.Where(z => !z.Category.Equals("01"))
                                             .GroupBy(a => new {a.Category, a.Vendor})
                                             .Select(b=> new MyItem{
                                                Vendor = b.First().Vendor,
                                                Cost = b.Sum(c => c.Cost),
                                                Category = b.First().Category
                                             }).ToList();

List<MyItem> final = new List<MyItem>();
final.AddRange(groupedItemsByCat01);
final.AddRange(groupedItemsByOther);

答案 2 :(得分:0)

在一个Linq-Expression中执行此操作有点棘手:

var newList = myItemList
    .Where(item => item.Category != "01")
    .GroupBy(item => new {item.Category, item.Vendor})
    .Select(group => new MyItem()
    {
        Vendor = group.Key.Vendor,
        Category = group.Key.Category,
        Cost = group.Sum(item => item.Cost)
    })
    .Union(new[]
    {
        new MyItem()
        {
            Vendor = "N/A",
            Category = "01",
            Cost = myItemList.Where(item => item.Category == "01").Sum(item => item.Cost)
        }
    });

foreach (var loItem in newList)
{
    Debug.WriteLine("Category = {0}, Vendor = {1}, Cost = {2}", 
        loItem.Category, loItem.Vendor, loItem.Cost);
}