我正在研究一些LINQ GroupBy逻辑,我无法想到如何优雅高效地使其工作。
基本上,我有一个IEnumerable<Thing>
对象(顺序正确!),其中每个Thing对象都有一个RootId属性。我想将这些对象分组到我正在使用的RootId上:
IEnumerable<Thing> things; // Already has value assigned
var groups =
(from thing in things
group thing by thing.RootId into thingGroup
select thingGroup.ToArray())
.ToList();
组的类型为List<Thing[]>
现在问题就在这里!
以上示例返回列表中的5个项目。但是,我如何将2个数组合并为1个,留下4个项目(同样,保持顺序)??
原因是因为其中2个项目具有不同的RootId,但我希望它们被视为相同,即组合在一起。
我要在LINQ语句之后连接并操作数组,但实际上它需要作为/ LINQ组的一部分来完成 - 任何想法?
如果需要更多示例或信息,请与我们联系。
谢谢!
合并标准将是一个手动过程,因此我考虑将其传递给groupby方法,如下所示:
var rootIdsToMerge = new List<Tuple<ID, ID>>
{
new Tuple<ID, ID>(rootIdOne, rootIdTwo),
new Tuple<ID, ID>(rootIdThree, rootIdFour)
};
因此任何RootId为rootIdOne的组项目都将与rootIdTwo为RootId的组项目合并,依此类推。
答案 0 :(得分:2)
由于您未使用分组Key
,因此您可以将映射中的Item2
与Item1
作为RootId
密钥关联,以便分组:
var groups =
(from thing in things
group thing by rootIdsToMerge.FirstOrDefault(e => e.Item2 == thing.RootId)?.Item1 ?? thing.RootId
into thingGroup
select thingGroup.ToArray())
.ToList();
或者在C#6之前(没有.?
运营商):
var groups =
(from thing in things
let mergeWith = rootIdsToMerge.FirstOrDefault(e => e.Item2 == thing.RootId)
group thing by mergeWith != null ? mergeWith.Item1 : thing.RootId
into thingGroup
select thingGroup.ToArray())
.ToList();
更新:如果您只想合并RootId
的列表,则可以使用Contains
和First
的组合:
List<ID> rootIdsToMerge = ...;
var groups =
(from thing in things
group thing by rootIdsToMerge.Contains(thing.RootId) ? rootIdsToMerge.First() : thing.RootId
into thingGroup
select thingGroup.ToArray())
.ToList();
的变种
List<List<ID>> rootIdsToMerge = ...;
类似于元组的初始变体:
var groups =
(from thing in things
group thing by rootIdsToMerge.FirstOrDefault(ids => ids.Contains(thing.RootId))?.First() ?? thing.RootId
into thingGroup
select thingGroup.ToArray())
.ToList();
或
var groups =
(from thing in things
let mergeList = rootIdsToMerge.FirstOrDefault(ids => ids.Contains(thing.RootId))
group thing by mergeList != null ? mergeList.First() : thing.RootId
into thingGroup
select thingGroup.ToArray())
.ToList();