[英]How do I convert a recursive object to a Collection in C#?
I have a recursive object, a linked list really:我有一个递归对象,一个真正的链表:
public class LinkedList
{
public string UniqueKey { get; set; }
public LinkedList LinkedList { get; set; }
}
LinkedList will have some object graph that will eventually end in LinkedList.LinkedList == null. LinkedList 将有一些最终以 LinkedList.LinkedList == null 结尾的对象图。
I would like to take all the objects in the graph and put them into a LinkedList collection so that I can iterate over them.我想获取图中的所有对象并将它们放入 LinkedList 集合中,以便我可以遍历它们。 How do I do this in C#?
我如何在 C# 中做到这一点? I feel as if there's a really easy way of going about this using yield or Linq voodoo?
我觉得好像有一种非常简单的方法可以使用 yield 或 Linq voodoo 来解决这个问题?
Something like this should work.像这样的东西应该工作。 If you have control over the class you can make it
IEnumerable
directly.如果您可以控制该类,则可以直接将其设置为
IEnumerable
。
public class LinkedListEnumerable : IEnumerable<string>
{
LinkedList list;
public LinkedListEnumerable(LinkedList l)
{
this.list = l;
}
public IEnumerator<string> GetEnumerator()
{
LinkedList l = list;
while(l != null)
{
yield return l.UniqueKey;
l = l.Next;
}
}
}
Then you can iterate over LinkedListEnumerable
with a for-each loop.然后,您可以使用 for-each 循环遍历
LinkedListEnumerable
。
Is this what you want?这是你想要的吗?
public class LinkedList
{
public string UniqueKey { get; set; }
public LinkedList LinkedList { get; set; }
public IEnumerable<LinkedList> GetAllNodes()
{
if (LinkedList != null)
{
yield return LinkedList;
foreach (var node in LinkedList.GetAllNodes())
yield return node;
}
}
}
There are no nice LINQ methods in the standard .NET library to allow some elegant LINQ voodoo, but you can use Generate
method from MoreLINQ project and write this:标准 .NET 库中没有很好的 LINQ 方法来允许一些优雅的 LINQ 巫术,但您可以使用MoreLINQ项目中的
Generate
方法并编写以下代码:
Enumerable
.Generate(list, l => l.LinkedList)
.TakeWhile(l => l != null).Select(l => l.UniqueKey);
It uses Generate
to create "infinite" list of all elements - it is not actually infinite, because it is generated lazily and we stop using it as soon as we find null
value at the end (using TakeWhile
).它使用
Generate
来创建所有元素的“无限”列表——它实际上并不是无限的,因为它是惰性生成的,一旦我们在最后找到null
值(使用TakeWhile
)就停止使用它。 Then we use Select
to return a sequence of values (instead of linked list nodes).然后我们使用
Select
返回一个值序列(而不是链表节点)。
This is essentially a nice declarative way of expressing the while
loop solution posted by Matthew (and it should have roughly similar performance).这本质上是表达 Matthew 发布的
while
循环解决方案的一种很好的声明方式(它应该具有大致相似的性能)。
EDIT The Generate
method looks like this:编辑
Generate
方法如下所示:
IEnumerable<T> Generate(T current, Func<T, T> generator) {
while(true) {
yield return current;
current = generator(current);
}
}
I have a data structure in my project where an object can have a parent, and multiple children of itself.我的项目中有一个数据结构,其中一个对象可以有一个父对象,也可以有多个子对象。 To get all the parents I can use this function:
要获得所有父母,我可以使用此功能:
public static IEnumerable<TModel> EnumerateParents<TModel>(TModel model, Func<TModel, TModel> parentSelector)
{
var curr = model;
while ((curr = parentSelector.Invoke(curr)) != null)
{
yield return curr;
}
}
Usage looks like this: _parents = ParentHelper.EnumerateParents(item, x => x.Parent).ToList();
用法如下所示:
_parents = ParentHelper.EnumerateParents(item, x => x.Parent).ToList();
I also made a function to enumerate all children which can be done with this function:我还做了一个函数来枚举所有可以用这个函数完成的孩子:
public static IEnumerable<TModel> EnumerateChildren<TModel>(TModel root, Func<TModel, IEnumerable<TModel>> childSelector)
{
var children = childSelector.Invoke(root);
if (children == null)
{
yield break;
}
foreach (var child in children)
{
yield return child;
foreach (var grandChild in EnumerateChildren(child, childSelector))
{
yield return grandChild;
}
}
}
which can be used like this: var children = ParentHelper.EnumerateChildren(item, x => x.Children)
可以这样使用:
var children = ParentHelper.EnumerateChildren(item, x => x.Children)
The last one is not asked in the question, but posted it anyways for if someone might need it.问题中没有问最后一个问题,但无论如何都会发布它以防有人需要它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.