拼合的IEnumerable有多个根节点,并选择Id属性 [英] Flatten IEnumerable with multiple root nodes and select Id property
问题描述
我有以下的层次,我需要拼合这一点,选择所有编号
秒。我已经尝试使用的SelectMany()
这样的 .SelectMany(结点=> node.Children)。选择(结点=> node.Id)
。这将导致 3,5,6 列表。是否有可能,使用LINQ来获取完整列表的 1,2,3,4,5,6,7
I have the following hierarchy and I need to flatten this and select all Id
s. I have tried using SelectMany()
like this .SelectMany(node => node.Children).Select(node => node.Id)
. This will result in a list of 3,5,6. Is it possible, using Linq to get the complete list 1,2,3,4,5,6,7?
- 节点(ID = 1)
- 节点(ID = 2)
- 节点(ID = 3)
- 节点(n = 5)
- 节点(ID = 6)
- 节点(ID = 7)
推荐答案
您可以使用下面的扩展方法压扁层次(请参阅下面的答案更新替代扁平化算法):
You can use following extension method for flattening hierarchy (see alternative flattening algorithm in answer update below):
public static IEnumerable<T> Flatten<T>( this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector) { foreach (var item in source) { yield return item; var children = childrenSelector(item); if (children == null) continue; foreach (var child in children.Flatten(childrenSelector)) yield return child; } }
我需要孩子选择和递归得到孩子。然后投射很简单:
I takes child selector and recursively yields children. Then projection is simple:
var result = nodes.Flatten(n => n.Children).Select(n => n.Id);
假定你有以下Node类:
Assume you have following Node class:
public class Node { public Node(int id, params Node[] children) { Id = id; if (children.Any()) Children = new List<Node>(children); } public int Id { get; set; } public List<Node> Children { get; set; } }
然后与样品等级:
Then with your sample hierarchy:
List<Node> nodes = new List<Node> { new Node(1), new Node(2, new Node(3)), new Node(4, new Node(5), new Node(6, new Node(7))) };
输出将是:
1, 2, 3, 4, 5, 6, 7
< STRONG>更新:您可以拼合层次不递归的使用情况(更好的性能):
UPDATE: You can flatten hierarchy without usage of recursion (for better performance):
public static IEnumerable<T> Flatten<T>( this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector) { Queue<T> queue = new Queue<T>(); foreach (var item in source) queue.Enqueue(item); while (queue.Any()) { T item = queue.Dequeue(); yield return item; var children = childrenSelector(item); if (children == null) continue; foreach (var child in children) queue.Enqueue(child); } }
这篇关于拼合的IEnumerable有多个根节点,并选择Id属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!