[英]C# Combine two lists with nested lists into one using LINQ
我在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",
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
Merge
是重要的一點。 它首先將a
和b
all放入一個列表中,然后GroupBy
名稱形成具有相同名稱的映射組。 在Select
需要每個組,使新的Map
與所有的內容Maps
在該組中(這是合並!)。 然后我對新的合並地圖的內容做了同樣的事情,並將MapProperty
組合在一起並合並/合並它們。
在您的具體情況下,您需要更多的工作和級別來合並所有內容。 我建議找到一種方法為樹中的每個級別創建一個Merge
方法,並從每個父級別調用下一級別,這樣你就不會得到一個龐大的 linq鏈。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.