c#IEnumerable <object> LINQ GroupBy - 合并2个组

时间:2017-06-15 18:12:43

标签: c# arrays linq merge

我正在研究一些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的组项目合并,依此类推。

1 个答案:

答案 0 :(得分:2)

由于您未使用分组Key,因此您可以将映射中的Item2Item1作为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的列表,则可以使用ContainsFirst的组合:

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();