LINQ递归函数?
让我们以这个 n 层深度结构为例:
public class SomeItem
{
public Guid ID { get;set; }
public string Name { get; set; }
public bool HasChildren { get;set; }
public IEnumerable<SomeItem> Children { get; set; }
}
如果我想通过 ID(结构中的任何位置)获取特定项目,是否有一些 LINQ 优点可以用来在单个语句中轻松获取它,或者我是否必须使用一些递归函数如下:
private SomeItem GetSomeItem(IEnumerable<SomeItem> items, Guid ID)
{
foreach (var item in items)
{
if (item.ID == ID)
{
return item;
}
else if (item.HasChildren)
{
return GetSomeItem(item.Children, ID);
}
}
return null;
}
Let's take this n-tier deep structure for example:
public class SomeItem
{
public Guid ID { get;set; }
public string Name { get; set; }
public bool HasChildren { get;set; }
public IEnumerable<SomeItem> Children { get; set; }
}
If I am looking to get a particular Item by ID (anywhere in the structure) is there some LINQ goodness I can use to easily get it in a single statement or do I have to use some recursive function as below:
private SomeItem GetSomeItem(IEnumerable<SomeItem> items, Guid ID)
{
foreach (var item in items)
{
if (item.ID == ID)
{
return item;
}
else if (item.HasChildren)
{
return GetSomeItem(item.Children, ID);
}
}
return null;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
LINQ 并没有真正很好地“执行”递归。您的解决方案似乎是合适的 - 尽管我不确定是否真的需要 HasChildren...为什么不只对没有孩子的项目使用空列表?
另一种方法是编写一个 DescendantsAndSelf 方法,该方法将返回所有后代(包括项目本身),如下所示;
然而,如果树很深,最终效率会非常低,因为每个项目都需要“通过”其祖先的所有迭代器。 Wes Dyer 关于此问题的博客,显示更有效的实施。
无论如何,如果您有这样的方法(无论它是如何实现的),您可以使用普通的“where”子句来查找项目(或 First/FirstOrDefault 等)。
LINQ doesn't really "do" recursion nicely. Your solution seems appropriate - although I'm not sure HasChildren is really required... why not just use an empty list for an item with no children?
An alternative is to write a
DescendantsAndSelf
method which will return all of the descendants (including the item itself), something like this;However, if the tree is deep that ends up being very inefficient because each item needs to "pass through" all the iterators of its ancestry. Wes Dyer has blogged about this, showing a more efficient implementation.
Anyway, if you have a method like this (however it's implemented) you can just use a normal "where" clause to find an item (or First/FirstOrDefault etc).
这是一个没有递归的情况。这避免了传递多层迭代器的成本,因此我认为它的效率与它们一样高。
像这样调用:
Here's one without recursion. This avoids the cost of passing through several layers of iterators, so I think it's about as efficient as they come.
Invoke like so:
希望这有帮助
hope this helps
重要的是要记住,您不需要使用 LINQ 执行所有操作,也不需要默认使用递归。使用数据结构时有一些有趣的选项。以下是一个简单的扁平化函数,以防有人感兴趣。
It is important to remember you don't need to do everything with LINQ, or default to recursion. There are interesting options when you use data structures. The following is a simple flattening function in case anyone is interested.
虽然有一些扩展方法可以在 LINQ 中启用递归(并且可能看起来像您的函数),但没有提供开箱即用的扩展方法。
这些扩展方法的示例可以在 此处或这里。
我想说你的功能很好。
While there are extension methods that enable recursion in LINQ (and probably look like your function), none are provided out of the box.
Examples of these extension methods can be found here or here.
I'd say your function is fine.