C# C使用LINQ将两个具有嵌套列表的列表合并为一个
我在c中有两个如下结构的列表。中的每个名称都是一个列表。我想把这两个列表合并成一个列表。以下伪代码显示了两个这样的列表以及结果的外观:C# C使用LINQ将两个具有嵌套列表的列表合并为一个,c#,linq,C#,Linq,我在c中有两个如下结构的列表。中的每个名称都是一个列表。我想把这两个列表合并成一个列表。以下伪代码显示了两个这样的列表以及结果的外观: <Servers> <Servers> +... +... +-- Server A,1 +-- Server A,1 | +...
<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
您可能一直在寻找.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",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Skips" },
}
}
};
var mapsB = new[]
{
new Map
{
Name = "MapA",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Times" },
}
},
new Map
{
Name = "MapC",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Skips" },
}
}
};
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}");
}
}
}
}
合并是重要的一点。它首先将a和b全部放在一个列表中,然后GroupBy name形成具有相同名称的地图组。Select将获取每个组,并使用该组中所有映射的内容创建一个新映射。这是“合并!”!。然后,我对新合并的地图的内容做了同样的操作,将MapProperty分组并合并它们
在您的特定情况下,您将需要更多的工作和级别来合并所有内容。我建议找到一种方法,为树中的每个级别创建一个合并方法,并从每个父级调用下一个级别,这样您就不会得到一个庞大的linq链。我认为您的想法是正确的。看起来您刚刚给嵌套联接传递了错误的参数!例如,在Maps join中,您试图加入coreServer.Maps和oImportList。。。我怀疑这应该是coreServer.Maps和importServer.Maps。在您的帮助下,我能够让代码正常工作,但后来我发现结果并不是我想要的列表。它只包含两个列表中都存在的元素。啊,对不起。。。我很少使用Join,所以我把它弄混了。我已使用GroupBy取消删除了一个答案,并选择了可能适合您的答案。我以前删除过它,因为我认为我走错了方向。
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);
}
}
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",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Skips" },
}
}
};
var mapsB = new[]
{
new Map
{
Name = "MapA",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Times" },
}
},
new Map
{
Name = "MapC",
Properties = new[]
{
new MapProperty { Name = "Jumps" },
new MapProperty { Name = "Skips" },
}
}
};
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