组内组 linq
Group inside group linq
我有这样的数据table:
我想将此分组 table 对于 FIELD A 和 FIELD B,
我组的第三个字段应该是FIELD C的列表,但必须按ID字段分组
最后的结果应该是这样的:
First Field | Second Field | Third Field
------------+--------------+----------------
5 | XXXX |(8) (2,6,3) (9)
5 | KKKK |(8,3)
第三个字段必须是列表的列表。
我如何使用 LINQ 执行此操作?
到目前为止我试过这个:
var trytogroup = (from p in datatable.AsEnumerable()
group p by new
{
ID = p["Id"].ToLong(),
FieldA = p["FieldA"].ToLong(),
FieldB = p["FieldB"].ToString()
} into g
select new
{
FirstField = g.Key.FieldA,
SecondField = g.Key.FieldB,
ThirdField = datatable.AsEnumerable().Where(p => p["FieldA"].ToLong() == g.Key.FieldA && p["FieldB"].ToString() == g.Key.FieldB).Select(p => p["FieldC"].ToLong()).GroupBy(x => x["Id"].ToLong()).Distinct().ToList()
});
您的查询有什么问题:
- 您不需要首先按三个字段分组。按 ID 分组应该在 FieldA 和 FieldB
所拥有的组内完成
- 获取 ThirdField 时,您无需再次查询数据表 - 您已经拥有所有需要的数据。您只需要按 ID
添加分组
正确查询:
from r in datatable.AsEnumerable()
group r by new {
FieldA = r.Field<long>("FieldA"),
FieldB = r.Field<string>("FieldB")
} into g
select new
{
First = g.Key.FieldA,
Second = g.Key.FieldB,
Third = g.GroupBy(r => r.Field<long>("ID"))
.Select(idGroup => idGroup.Select(i => i.Field<long>("FieldC")).ToList())
}
如果您更喜欢 lambda,您的查询可能如下所示:
dataSource
.GroupBy(item => new { item.FieldA, item.FieldB })
.Select(group => new
{
First = group.Key.FieldA,
Second = group.Key.FieldB,
Third = group.GroupBy(q => q.Id).Select(q => q.Select(e => e.FieldC).ToArray()).ToArray()
}).ToArray();
只是一些小笔记。 .GroupBy
使用 Lookup
获取 Grouping
,因此当不需要延迟执行时,可以通过将 .GroupBy(
替换为 .ToLookup(
来避免一些开销。
每个 Grouping
中的元素都是 stored in array,所以我看不出转换它们有多大用处 .ToList
(但你可以节省一点 space如果你转换它们 .ToArray
)。
DataTable.AsEnumerable
使用 .Rows.Cast<TRow>()
,但在 DataView
通常不需要的排序或过滤时似乎也会做一些额外的事情。
var groups = datatable.Rows.Cast<DataRow>()
.ToLookup(r => Tuple.Create(
r["FieldA"] as long?,
r["FieldB"]?.ToString()
))
.Select(g => Tuple.Create(
g.Key.Item1,
g.Key.Item2,
g.ToLookup(r => r["ID"] as long?, r => r["FieldC"] as long?)
)).ToList();
像往常一样,premature optimization is the root of all evil但我认为这些信息可能有用。
我有这样的数据table:
我想将此分组 table 对于 FIELD A 和 FIELD B, 我组的第三个字段应该是FIELD C的列表,但必须按ID字段分组
最后的结果应该是这样的:
First Field | Second Field | Third Field
------------+--------------+----------------
5 | XXXX |(8) (2,6,3) (9)
5 | KKKK |(8,3)
第三个字段必须是列表的列表。
我如何使用 LINQ 执行此操作?
到目前为止我试过这个:
var trytogroup = (from p in datatable.AsEnumerable()
group p by new
{
ID = p["Id"].ToLong(),
FieldA = p["FieldA"].ToLong(),
FieldB = p["FieldB"].ToString()
} into g
select new
{
FirstField = g.Key.FieldA,
SecondField = g.Key.FieldB,
ThirdField = datatable.AsEnumerable().Where(p => p["FieldA"].ToLong() == g.Key.FieldA && p["FieldB"].ToString() == g.Key.FieldB).Select(p => p["FieldC"].ToLong()).GroupBy(x => x["Id"].ToLong()).Distinct().ToList()
});
您的查询有什么问题:
- 您不需要首先按三个字段分组。按 ID 分组应该在 FieldA 和 FieldB 所拥有的组内完成
- 获取 ThirdField 时,您无需再次查询数据表 - 您已经拥有所有需要的数据。您只需要按 ID 添加分组
正确查询:
from r in datatable.AsEnumerable()
group r by new {
FieldA = r.Field<long>("FieldA"),
FieldB = r.Field<string>("FieldB")
} into g
select new
{
First = g.Key.FieldA,
Second = g.Key.FieldB,
Third = g.GroupBy(r => r.Field<long>("ID"))
.Select(idGroup => idGroup.Select(i => i.Field<long>("FieldC")).ToList())
}
如果您更喜欢 lambda,您的查询可能如下所示:
dataSource
.GroupBy(item => new { item.FieldA, item.FieldB })
.Select(group => new
{
First = group.Key.FieldA,
Second = group.Key.FieldB,
Third = group.GroupBy(q => q.Id).Select(q => q.Select(e => e.FieldC).ToArray()).ToArray()
}).ToArray();
只是一些小笔记。 .GroupBy
使用 Lookup
获取 Grouping
,因此当不需要延迟执行时,可以通过将 .GroupBy(
替换为 .ToLookup(
来避免一些开销。
每个 Grouping
中的元素都是 stored in array,所以我看不出转换它们有多大用处 .ToList
(但你可以节省一点 space如果你转换它们 .ToArray
)。
DataTable.AsEnumerable
使用 .Rows.Cast<TRow>()
,但在 DataView
通常不需要的排序或过滤时似乎也会做一些额外的事情。
var groups = datatable.Rows.Cast<DataRow>()
.ToLookup(r => Tuple.Create(
r["FieldA"] as long?,
r["FieldB"]?.ToString()
))
.Select(g => Tuple.Create(
g.Key.Item1,
g.Key.Item2,
g.ToLookup(r => r["ID"] as long?, r => r["FieldC"] as long?)
)).ToList();
像往常一样,premature optimization is the root of all evil但我认为这些信息可能有用。