[英]Use Linq to flatten a nested list instead of a foreach loop
我有一個經常性的課 - 我在下面簡化了它。
public class SiloNode
{
public string Key { get; private set; }
public string Url { get; private set; }
public List<SiloNode> Children { get; private set; }
}
雖然理論上它可以永遠嵌套,但節點只會下降兩個級別。 因此,頂級節點可以有一個孩子,但孩子不能有孩子。
我有一個主列表,其中包含所有頂級節點及其嵌套的子節點。
但是,我需要將所有節點放入一個單獨的平面列表 - 節點1,后跟其子節點,然后是節點2等。
我在這個領域的知識是有限的,但我可以在主列表上執行類似foreach
的操作並創建一個新列表,如下所示:
public IEnumerable<SiloNode> GetLinks(IEnumerable<SiloNode> masterList)
{
var newList = new List<SiloNode>();
foreach (var node in masterList)
{
newList.Add(node);
newList.AddRange(node.Children);
}
return newList;
}
但是,我知道可能有更好的方法可用,但我無法弄清楚如何將foreach
轉換為Linq
語句,它將執行相同的操作。 換句話說,一起選擇父級及其子級。
任何幫助贊賞。
您可以使用SelectMany
,只需連接單個父項及其子項:
List<SiloNode> newList = masterList.SelectMany(n => new[]{ n }.Concat(n.Children)).ToList();
masterList
已包含父節點,並連接子節點
var nodes = masterList.Concat(masterList.SelectMany(x=> x.Children));
如果只有兩個級別,那么應該這樣做:
public IEnumerable<SiloNode> GetLinks(IEnumerable<SiloNode> masterList)
{
return masterList.SelectMany(m => new SiloNode[] { m }.Concat(m.Children));
}
如果你想保留訂單並壓平不止一個級別的孩子,我認為這樣的事情會很好。 var nodes = GetLinks(masterList);
或者在循環中使用它for(var node in GetLinks(masterList))
public IEnumerable<SiloNode> GetLinks(IEnumerable<SiloNode> masterList)
{
foreach(var node in masterList)
{
yield return node;
foreach(var children in GetLinks(node.Children))
yield return children;
}
}
我以前見過這個回答,但是找不到問題。 這樣做你想要的,而不是在節點結構中真正深入遞歸:
public IEnumerable<SiloNode> Flatten(IEnumerable<SiloNode> nodes)
{
var queue = new Queue<SiloNode>();
foreach (var node in nodes)
{
queue.Enqueue(node);
}
while (queue.Count > 0)
{
var node = queue.Dequeue();
foreach (var child in node.Children)
{
queue.Enqueue(child);
}
yield return node;
}
}
編輯:這不保留您想要的順序,但您可以使用堆棧而不是隊列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.