SelectMany 三层深度

Posted

技术标签:

【中文标题】SelectMany 三层深度【英文标题】:SelectMany Three Levels Deep 【发布时间】:2010-10-13 00:42:04 【问题描述】:

我可以使用 SelectMany 展平集合中子集合的结果:

 // a list of Foos, a Foo contains a List of Bars
 var source = new List<Foo>()  ... ;

 var q = source.SelectMany(foo => foo.Bar)
     .Select(bar => bar.barId)
 .ToList();

这给了我 Foo 列表中所有 Bar Id 的列表。当我尝试深入三层时,返回的结果不正确。

 var q = source.SelectMany(foo => foo.Bar)
     .SelectMany(bar => bar.Widget)
         .Select(widget => widget.WidgetId)
 .ToList();

我应该如何使用 SelectMany 来获取我的 Foos 列表中所有 Bars 中的所有小部件的列表?

编辑 我用错了上面的句子,但代码反映了目标。我正在寻找所有小部件 ID 的列表,而不是小部件。

“不正确”的结果并不是所有的小部件 ID 都被返回。

【问题讨论】:

对我来说看起来不错。 “返回的结果不正确”不是描述性错误消息,您会得到什么,您期望什么? 【参考方案1】:

您的查询将返回所有小部件 ID,而不是所有小部件。如果您只想要小部件,只需使用:

var q = source.SelectMany(foo => foo.Bar)
              .SelectMany(bar => bar.Widget)
              .ToList();

如果这仍然给出“不正确的结果”,请以方式解释它是不正确的结果。示例代码会很有帮助:)

编辑:好的,如果你想要小部件 ID,你的原始代码应该没问题:

var q = source.SelectMany(foo => foo.Bar)
              .SelectMany(bar => bar.Widget)
              .Select(widget => widget.WidgetId)
              .ToList();

也可以写成

var q = (from foo in source
         from bar in foo.Bar
         from widget in bar.Widget
         select widgetId).ToList();

如果你喜欢查询表达式格式。

这确实应该有效 - 如果它有效,则表明您的数据有问题。

我们之前应该检查一下 - 这只是 LINQ to Objects,还是更高级的提供程序(例如 LINQ to SQL)?

【讨论】:

是的,我的意思是说所有小部件 ID,而不是返回的小部件。当我链接 SelectMany(...).SelectMany(...).Select() 时,由于某种原因,最后一个选择不会返回所有 Widget Id 的列表。 它的 LINQ-to-Objects。好的,只要查询在我期望它如何工作方面是准确的,我就可以将问题缩小到数据并从那里开始,谢谢。【参考方案2】:
var q = (
    from f in foo
    from b in f.Bars
    from w in b.Widgets
    select w.WidgetId
   ).ToList();

还要注意,如果你想要唯一的列表,你可以用 .Distinct().ToList() 代替。

【讨论】:

假设每个 Foo 有一个 Bar,每个 Bar 有一个 Widget。 @Jon 但这不正是他正在做的事情吗? 没有。他为每个 Foo 选择多个 Bars - 这就是 SelectMany 所做的。 查看评论:“一个 Foo 包含一个酒吧列表”。您的修改版本与我的基本相同,只需要两倍的代码行数(如果真的不需要 ToList(),则需要三倍的代码行数)。有时查询表达式比它们的价值更麻烦:) @Jon 没错,不习惯模型说 foo.Bar 代表 1-n :( --updated 仅使用 1-n 版本。【参考方案3】:
       var q = source.SelectMany(foo => foo.Bar)
          .SelectMany(bar => bar.Widget,(bar,widget) => widget.WidgetId)
          .ToList();

我们可以调用 SelectMany() 的重载,允许我们使用 lambda 表达式指定投影

【讨论】:

这里我们最终调用了三个方法而不是四个

以上是关于SelectMany 三层深度的主要内容,如果未能解决你的问题,请参考以下文章

具有三层深度嵌套模型的查询集过滤器(多个一对多关系)

深度学习入门-1透彻理解卷积的三层含义:从“卷积”到“图像卷积操作”再到“卷积神经网络”的含义(学习笔记)

讲义推荐理解支持向量机的三层境界

Flink Time深度解析

这样的三层BP神经网络怎么建立: 4个输入节点,3个输出节点,隐含层节点数为7,传递函数均采用Sigmoid函数!

[深度长文] 996的经济学