ChatGPT解决这个技术问题 Extra ChatGPT

按多列分组

如何在 LINQ 中对多列进行 GroupBy

SQL中类似的东西:

SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>

如何将其转换为 LINQ:

QuantityBreakdown
(
    MaterialID int,
    ProductID int,
    Quantity float
)

INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity)
SELECT MaterialID, ProductID, SUM(Quantity)
FROM @Transactions
GROUP BY MaterialID, ProductID

l
leppie

使用匿名类型。

例如

group x by new { x.Column1, x.Column2 }

如果您不熟悉使用匿名类型进行分组,那么在此示例中使用“new”关键字会很神奇。
如果带有 nHibernate 的 mvc 因 dll 问题而出现错误。 GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new { Key1 = key.Column1, Key2 = key.Column2 , Result = group.ToList() });
我认为在这种情况下,新对象将通过引用进行比较,因此不匹配 - 不分组。
@HoGo 匿名类型对象 implement their own Equals and GetHashCode 方法,用于对对象进行分组。
当您刚接触 Linq 时,将输出数据结构可视化有点困难。这会创建一个使用匿名类型作为键的分组吗?
i
iliketocode

程序样本:

.GroupBy(x => new { x.Column1, x.Column2 })

返回的对象是什么类型?
@MGG_Soft 这将是一个匿名类型
@Tom 这应该按原样工作。当您跳过命名匿名类型的字段时,C# 假定您要使用投影中最终访问的属性/字段的名称。 (所以你的例子相当于 Mo0gles')
@Crisfole 是的,我完全同意在大多数情况下这是真的。但是,有时编译器无法推断字段名称,必须明确指定它们。就像您收到“无效的匿名类型声明符”编译错误一样。它发生在我身上,也发生在 thalesfc 身上,因此发表了评论。
找到了我的答案。我需要定义一个包含 Column1 和 Column2 属性的新实体(MyViewEntity),返回类型是:IEnumerable> 和分组代码片段是:MyEntityList.GroupBy(myEntity => new MyViewEntity { Column1 = myEntity. Column1, Column2 = myEntity.Column2 });
s
splattne

好的,这是:

var query = (from t in Transactions
             group t by new {t.MaterialID, t.ProductID}
             into grp
                    select new
                    {
                        grp.Key.MaterialID,
                        grp.Key.ProductID,
                        Quantity = grp.Sum(t => t.Quantity)
                    }).ToList();

+1 - 感谢您提供全面的示例。另一个答案的片段太短且没有上下文。您还显示了一个聚合函数(在这种情况下为 Sum)。非常有帮助。我发现将聚合函数(即 MAX、MIN、SUM 等)与分组并排使用是一种常见的场景。
这里:stackoverflow.com/questions/14189537/…,当分组基于单个列时,它显示了一个数据表,其名称是已知的,但是如果要进行分组的列必须动态生成,怎么办?
这对于理解分组的概念和在其上应用聚合非常有帮助。
很好的例子......正是我想要的。我什至需要聚合,所以这是一个完美的答案,即使我正在寻找 lambda,我从中得到了足够的东西来解决我的需求。
拥有 grp.Key。是我让它工作所需要的,谢谢!
M
Milan

对于按多列分组,请改用此方法...

GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new 
{ 
  Key1 = key.Column1,
  Key2 = key.Column2,
  Result = group.ToList() 
});

同样的方式你可以添加 Column3、Column4 等。


这非常有帮助,应该得到更多的支持! Result 包含链接到所有列的所有数据集。非常感谢!
注意:我必须使用 .AsEnumerable() 而不是 ToList()
太棒了,谢谢你。这是我的例子。请注意,GetFees 返回 IQueryable RegistryAccountDA.GetFees(registryAccountId, fromDate, toDate) .GroupBy(x => new { x.AccountId, x.FeeName }, (key, group) => new { AccountId = key.AccountId , FeeName = key.FeeName, AppliedFee = group.Sum(x => x.AppliedFee) ?? 0M }).ToList();
是否可以从此查询中获取未分组的其他列?如果有对象数组,我想将此对象按两列分组,但从对象中获取所有属性,而不仅仅是这两列。
N
Nathan Tregillus

从 C# 7 开始,您还可以使用值元组:

group x by (x.Column1, x.Column2)

或者

.GroupBy(x => (x.Column1, x.Column2))

好吧,我认为您最后缺少一个额外的 ) 。您没有关闭 ()
我已经添加了它。
.GroupBy(x => new { x.Column1, x.Column2})
表达式树可能不包含元组文字。这就是为什么.GroupBy(x => new { x.Column1, x.Column2})
A
AlbertK

C# 7.1 或更高版本 使用 TuplesInferred tuple element names(目前它仅适用于 linq to objects,并且在需要表达式树时不受支持,例如 someIQueryable.GroupBy(...)Github issue):

// declarative query syntax
var result = 
    from x in inMemoryTable
    group x by (x.Column1, x.Column2) into g
    select (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity));

// or method syntax
var result2 = inMemoryTable.GroupBy(x => (x.Column1, x.Column2))
    .Select(g => (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity)));

C# 3 或更高版本 使用 anonymous types

// declarative query syntax
var result3 = 
    from x in table
    group x by new { x.Column1, x.Column2 } into g
    select new { g.Key.Column1, g.Key.Column2, QuantitySum = g.Sum(x => x.Quantity) };

// or method syntax
var result4 = table.GroupBy(x => new { x.Column1, x.Column2 })
    .Select(g => 
      new { g.Key.Column1, g.Key.Column2 , QuantitySum= g.Sum(x => x.Quantity) });

哇谢谢你。这在大脑上留下了印记,并增加了可能性。
极好的 - - - :) :)
J
Jay Bienvenu

您还可以使用 Tuple<> 进行强类型分组。

from grouping in list.GroupBy(x => new Tuple<string,string,string>(x.Person.LastName,x.Person.FirstName,x.Person.MiddleName))
select new SummaryItem
{
    LastName = grouping.Key.Item1,
    FirstName = grouping.Key.Item2,
    MiddleName = grouping.Key.Item3,
    DayCount = grouping.Count(), 
    AmountBilled = grouping.Sum(x => x.Rate),
}

注意:Linq To 实体不支持创建新元组
C
Chris Smith

尽管这个问题询问的是按类属性分组,但如果您想针对 ADO 对象(如 DataTable)按多列分组,则必须将“新”项分配给变量:

EnumerableRowCollection<DataRow> ClientProfiles = CurrentProfiles.AsEnumerable()
                        .Where(x => CheckProfileTypes.Contains(x.Field<object>(ProfileTypeField).ToString()));
// do other stuff, then check for dups...
                    var Dups = ClientProfiles.AsParallel()
                        .GroupBy(x => new { InterfaceID = x.Field<object>(InterfaceField).ToString(), ProfileType = x.Field<object>(ProfileTypeField).ToString() })
                        .Where(z => z.Count() > 1)
                        .Select(z => z);

我无法执行 Linq 查询“group c by new{c.Field("Title"),c.Field("CIF")}”,您为我节省了很多时间!!最后的查询是:“group c by new{titulo= c.Field("Title"),cif=c.Field("CIF")} "
s
sepehr
var Results= query.GroupBy(f => new { /* add members here */  });

对前面的答案没有添加任何内容。
O
Ogglas

需要注意的是,您需要为 Lambda 表达式发送对象,并且不能将实例用于类。

例子:

public class Key
{
    public string Prop1 { get; set; }

    public string Prop2 { get; set; }
}

这将编译,但每个周期会生成一个密钥。

var groupedCycles = cycles.GroupBy(x => new Key
{ 
  Prop1 = x.Column1, 
  Prop2 = x.Column2 
})

如果您不想命名关键属性然后检索它们,您可以这样做。这将GroupBy正确地为您提供关键属性。

var groupedCycles = cycles.GroupBy(x => new 
{ 
  Prop1 = x.Column1, 
  Prop2= x.Column2 
})

foreach (var groupedCycle in groupedCycles)
{
    var key = new Key();
    key.Prop1 = groupedCycle.Key.Prop1;
    key.Prop2 = groupedCycle.Key.Prop2;
}

K
Kai Hartmann
.GroupBy(x => x.Column1 + " " + x.Column2)

结合 Linq.Enumerable.Aggregate() 这甚至允许按动态数量的属性进行分组:propertyValues.Aggregate((current, next) => current + " " + next)
这是一个比任何人都认为的更好的答案。如果在 column1 不同的情况下(“ab”“cde”将匹配“abc”“de”),添加到 column2 的 column1 可能等于相同的组合实例,则可能会出现问题。也就是说,如果您不能使用动态类型,这是一个很好的解决方案,因为您在 group by 之后在单独的表达式中预先构造了 lambda。
"ab" "cde" 实际上不应该匹配 "abc" "de",因此中间有空格。
“abc de”“”和“abc”“de”呢?
J
John

将 x 按新 { x.Col, x.Col} 分组


L
Let's Enkindle

.GroupBy(x => (x.MaterialID, x.ProductID))


考虑添加有关此代码如何解决问题的说明。
D
Dani

对于 VB 和匿名/lambda:

query.GroupBy(Function(x) New With {Key x.Field1, Key x.Field2, Key x.FieldN })