LINQ GroupBy具有动态的列组

spo*_*rts 4 c# linq group-by

我有这样一张桌子:

 variety category  quantity
----------------------------------------------
  rg      pm         10
  gs      pm          5
  rg      com         8
Run Code Online (Sandbox Code Playgroud)

我想GroupBy根据这些bool参数制作一个:

  • IncludeVariety
  • IncludeCategory

例如:

IncludeVariety = true;
IncludeCategory = true;
Run Code Online (Sandbox Code Playgroud)

会回来这个:

 variety category  quantity
----------------------------------------------
  rg      pm         10
  gs      pm          5
  rg      com         8
Run Code Online (Sandbox Code Playgroud)

还有这个:

IncludeVariety = true;
IncludeCategory = false;
Run Code Online (Sandbox Code Playgroud)

会回来这个:

  variety category  quantity
----------------------------------------------
    rg      -         18
    gs      -          5
Run Code Online (Sandbox Code Playgroud)

还有这个:

IncludeVariety = false;
IncludeCategory = true;
Run Code Online (Sandbox Code Playgroud)

会回来这个:

  variety category  quantity
----------------------------------------------
     -      pm         15
     -      com         8
Run Code Online (Sandbox Code Playgroud)

你明白了......

问题:如何使用LINQ实现此目的?

重要提示:我已将问题减少到两个bool变量(IncludeVarietyIncludeCategory)但实际上我将有更多列(比如五个)

我无法弄清楚如何动态生成查询(.GroupBy.Select):

 rows.GroupBy(r => new { r.Variety, r.Category })
 .Select(g => new 
  {
        Variety = g.Key.Variety,
        Category = g.Key.Category,
        Quantity = g.Sum(a => a.Quantity),
  });

 rows.GroupBy(r => new { r.Category })
 .Select(g => new 
  {
        Variety = new {},
        Category = g.Key.Category,
        Quantity = g.Sum(a => a.Quantity),
  });

 rows.GroupBy(r => new { r.Variety })
 .Select(g => new 
  {
        Variety = g.Key.Variety,
        Category = new {},
        Quantity = g.Sum(a => a.Quantity),
  });
Run Code Online (Sandbox Code Playgroud)

一个类似的事情,我已经在过去所做的是串联Where的,如:

  var query = ...

  if (foo) {
       query = query.Where(...)
  }

  if (bar) {
       query = query.Where(...)
  }

  var result = query.Select(...)
Run Code Online (Sandbox Code Playgroud)

我可以在这做些什么吗?

Rob*_*Kee 8

var results=items
  .Select(i=>
    new {
      variety=includevariety?t.variety:null,
      category=includecategory?t.category:null,
      ...
    })
  .GroupBy(g=>
    new { variety, category, ... }, g=>g.quantity)
  .Select(i=>new {
    variety=i.Key.variety,
    category=i.Key.category,
    ...
    quantity=i.Sum()
  });
Run Code Online (Sandbox Code Playgroud)

缩短:

var results=items
  .GroupBy(g=>
    new {
      variety=includevariety?t.variety:null,
      category=includecategory?t.category:null,
      ... 
    }, g=>g.quantity)
  .Select(i=>new {
    variety=i.Key.variety,
    category=i.Key.category,
    ...
    quantity=i.Sum()
  });
Run Code Online (Sandbox Code Playgroud)


Jef*_*ado 6

如果您需要真正动态,请使用Scott Gu的Dynamic LINQ库.

您只需要确定要在结果和组中包含哪些列.

public static IQueryable GroupByColumns(this IQueryable source,
    bool includeVariety = false,
    bool includeCategory = false)
{
    var columns = new List<string>();
    if (includeVariety) columns.Add("Variety");
    if (includeCategory) columns.Add("Category");
    return source.GroupBy($"new({String.Join(",", columns)})", "it");
}
Run Code Online (Sandbox Code Playgroud)

然后你可以把它们分组.

var query = rows.GroupByColumns(includeVariety: true, includeCategory: true);
Run Code Online (Sandbox Code Playgroud)