草庐IT

c# - 在 LINQ 中表达递归

coder 2023-07-11 原文

我正在为分层数据源编写一个 LINQ 提供程序。我发现通过编写示例展示我想如何使用它,然后编写代码来支持这些用例来设计我的 API 是最简单的。

我遇到的一件事是在 LINQ 语句中以一种简单/可重用/优雅的方式表达“深度查询”或递归。换句话说,什么是最好的区分方式:

from item in immediate-descendants-of-current-node where ... select item

对比:

from item in all-descendants-of-current-node where ... select item

(编辑:请注意,以上示例都不一定反射(reflect)我想要的查询结构。我对任何表达递归/深度的好方法感兴趣)

请注意 我不是在问如何实现这样的提供程序,或者如何以允许递归的方式编写我的 IQueryable 或 IEnumerable。我从编写 LINQ 查询并利用我的提供程序的人的角度来问 - 他们表达是否要递归的直观方式是什么?

数据结构类似于典型的文件系统:文件夹可以包含子文件夹的集合,文件夹也可以包含项目的集合。所以 myFolder.Folders 代表所有作为 myFolder 的直接子级的文件夹,而 myFolder.Items 包含直接在 myFolder 中的所有项目。这是站点层次结构的基本示例,很像具有文件夹和页面的文件系统:

(F)Products
    (F)Light Trucks
        (F)Z150
            (I)Pictures
            (I)Specs
            (I)Reviews
        (F)Z250
            (I)Pictures
            (I)Specs
            (I)Reviews
        (F)Z350
            (I)Pictures
            (I)Specs
            (I)Reviews
        (I)Splash Page
    (F)Heavy Trucks
    (F)Consumer Vehicles
    (I)Overview 

如果我写:

from item in lightTrucks.Items where item.Title == "Pictures" select item

表达查询获取 Light Trucks 下的所有项目或仅获取直接项目的意图的最直观方式是什么?区分这两种意图的干扰最少、摩擦最小的方法?

我的第一目标是能够将此 LINQ 提供程序转交给对 LINQ 有一般了解的其他开发人员,并允许他们编写递归查询和列表查询,而无需为他们提供有关编写递归 lambda 的教程。鉴于看起来不错的用法,我可以针对它编写提供程序代码。

补充说明:(我真的很不擅长交流这个!)- 这个 LINQ 提供程序是针对外部系统的,它不是简单地遍历对象图,在这种特定情况下也不是递归表达式 实际上转化为任何类型的真正的递归事件。只需要一种方法来区分“深度”查询和“浅层”查询。

那么,您认为最好的表达方式是什么?或者是否有一种我错过的标准表达方式?

最佳答案

Linq-toXml 可以很好地处理这个问题,有一个 XElement.Elements()/.Nodes() 操作来获取直接子项,还有一个 XElement.Descendents()/DescendentNodes() 操作来获取所有后代。你会认为这是一个例子吗?

总结 Linq-to-Xml 的行为...每个导航函数对应于 XPath 中的一个轴类型 (http://www.w3schools.com/xpath/xpath_axes.asp)。如果导航功能选择元素,则使用轴名称。如果导航功能选择节点,则使用轴名称并附加节点。

例如,有函数 Descendants() 和 DescendantsNode() 对应于 XPath 的后代轴,返回 XElement 或 XNode。

异常情况是最常用的情况,即子轴。在 XPath 中,如果未指定轴,则这是使用的轴。为此,linq-to-xml 导航函数不是 Children() 和 ChildrenNodes(),而是 Elements() 和 Nodes()。

XElement 是 XNode 的子类型。 XNode 包括 HTML 标签之类的东西,但也包括 HTML 注释、cdata 或文本。 XElements 是一种 XNode,但特指 HTML 标签。 XElements 因此有一个标签名称,并支持导航功能。

现在在 Linq-to-XML 中链接导航不像在 XPath 中那么容易。问题在于导航函数返回集合对象,而导航函数应用于非集合。考虑 XPath 表达式,它选择一个表标记作为直接子标记,然后选择任何后代表数据标记。我认为这看起来像“./children::table/descendants::td”或“./table/descendants::td”

使用 IEnumerable<>::SelectMany() 可以调用集合上的导航函数。上面的等价物看起来像 .Elements("table").SelectMany(T => T.Descendants("td"))

关于c# - 在 LINQ 中表达递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/732281/

有关c# - 在 LINQ 中表达递归的更多相关文章

  1. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  2. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  3. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  4. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  5. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  6. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  7. ruby - 为什么我用递归得到 "stack level too deep"? - 2

    我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大

  8. c# - C# 中的 Flatten Ruby 方法 - 2

    我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume

  9. ruby - 构建网络蜘蛛时,应该使用递归吗? - 2

    构建一个深度优先的网络蜘蛛,这意味着它将访问第一页上的所有链接,然后转到每个链接,并访问所有第二页上的链接...你应该使用递归吗?我发现这是CPU密集型的。defrecursion()linkz_on_first_page.eachdo|link|recursion(link)endendrecursion(firstpage) 最佳答案 绝对不是,由于万维网的实际性质,您很快就会遇到问题。当您访问带有主导航部分的网站时,每个页面都链接到其他页面,您就进入了一个无限循环。您可以跟踪您处理了哪些链接,但即便如此,递归循环并不真正适合万

  10. ruby - 可以像在 C# 中使用#region 一样在 Ruby 中使用 begin/end 吗? - 2

    我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用

随机推荐