加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#使用LINQ将带有嵌套列表的两个列表合并为一个

发布时间:2020-12-15 20:58:50 所属栏目:百科 来源:网络整理
导读:我在c#中有两个以下结构列表. 中的每个名称是一个清单.我想将这两个列表合并到一个List Server中.以下伪代码显示两个这样的列表以及结果应如何: Servers Servers+... +...+-- Server A,1 +-- Server A,1| +... | +... | +--Maps | +--Maps| +--Map x | +--M
我在c#中有两个以下结构列表. <>中的每个名称是一个清单.我想将这两个列表合并到一个List< Server>中.以下伪代码显示两个这样的列表以及结果应如何:

<Servers>                           <Servers>
+...                                +...
+-- Server A,1                      +-- Server A,1
|       +...                        |       +...    
|       +--<Maps>                   |       +--<Maps>
|           +--Map x                |           +--Map x
|               +...                |               +...    
|               +--<Times>          |               +--<Times>
|                   +--Time i       |                   +--Time l
|                   +--Time j       |               +--<Jumps>
|               +--<Jumps>          |                   +--Jump t
|                   +--Jump s       |                   +--Jump u
|           +--Map y                |           +--Map z
|               +...                |               +...
|               +--<Times>          |               +--<Jumps>  
|                   +-- Time k      |                   +--Jump v
+-- Server B,1                      +-- Server B,2

结果应该是:

<Servers>
+...
+-- Server A,1
|   +...
|   +--<Maps>
|       +-- Map x
|           +...
|           +--<Times>
|               +--Time i
|               +--Time j
|               +--Time l
|           +--<Jumps>
|               +--Jump s
|               +--Jump t
|               +--Jump u
|       +-- Map y
|           +...
|           +--<Times>
|               +--Time k
|       +-- Map z
|           +...
|           +--<Jumps>
|               +--Jump v
+-- Server B,1
+-- Server B,2

我尝试使用linq的完全外连接,但结果也不是我想要的,因为我不理解具有相同密钥的服务器不匹配,所以我总是有相同服务器的重复数据.那是我停止尝试使用linq并且只是使用循环手动合并列表的时候.

下面的代码为我提供了所需的结果列表.现在我将使用它,直到找到更好的方法.使用linq是否有简单/更短的方式?使用lambda表达式?

foreach (Server importServer in oImportList)
        {
            if (!CoreList.Contains(importServer))
            {
                CoreList.Add(importServer);
                continue;
            }

            Server coreServer = CoreList.FirstOrDefault(o => o.Equals(importServer));
            coreServer.Name = importServer.Name;
            coreServer.KZTimerVersion = importServer.KZTimerVersion;
            foreach(Map importMap in importServer.Maps)
            {
                if (!coreServer.Maps.Contains(importMap))
                {
                    coreServer.Maps.Add(importMap);
                    continue;
                }
                Map coreMap = coreServer.Maps.FirstOrDefault(o => o.Equals(importMap));
                coreMap.Jumps.Concat(importMap.Jumps);
                coreMap.Times.Concat(importMap.Times);
            }
        }

解决方法

您可能一直在寻找.Union,但这并不涉及嵌套列表,因此我认为这不是您真正需要的.我设置了一个完整的例子 – 虽然结构与你的结构不一样,但我认为你可以很容易地应用核心linq:

using System;
using System.Collections.Generic;
using System.Linq;

public class Map
{
    public string Name { get; set; }
    public IEnumerable<MapProperty> Properties { get; set; }
}

public class MapProperty
{
    public string Name { get; set; }
}

public class Test
{
    public static IEnumerable<Map> Merge(IEnumerable<Map> a,IEnumerable<Map> b)
    {
        return a.Concat(b)
            .GroupBy(map => map.Name)
            .Select(mg => new Map
            {
                Name = mg.Key,Properties = mg.SelectMany(v => v.Properties)
                    .GroupBy(p => p.Name)
                    .Select(pg => new MapProperty { Name = pg.Key })
            });
    }

    public static void Main()
    {
        var mapsA = new[]
        {
            new Map
            {
                Name = "MapA",Properties = new[]
                {
                    new MapProperty { Name = "Jumps" },new MapProperty { Name = "Hops" },}
            },new Map
            {
                Name = "MapB",new MapProperty { Name = "Skips" },}
            }
        };
        var mapsB = new[]
        {
            new Map
            {
                Name = "MapA",new MapProperty { Name = "Times" },new Map
            {
                Name = "MapC",}
            }
        };

        var mapsC = Merge(mapsA,mapsB);

        foreach (var map in mapsC)
        {
            Console.WriteLine($"{map.Name}");
            foreach (var prop in map.Properties)
            {
                Console.WriteLine($"t{prop.Name}");
            }
        }
    }
}

输出:

MapA
    Jumps
    Hops
    Times
MapB
    Jumps
    Skips
MapC
    Jumps

合并是重要的一点.它首先将a和b all放入一个列表中,然后GroupBy名称形成具有相同名称的映射组. Select选取每个组并使用该组中所有地图的内容创建一个新Map(这是合并!).然后我对新的合并地图的内容做了同样的事情,并将MapPropertys组合在一起并合并/合并它们.

在您的具体情况下,您需要更多的工作和级别来合并所有内容.我建议找到一种方法为树中的每个级别创建一个Merge方法,并从每个父级别调用下一级别,这样你就不会得到一个庞大的linq链.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读