【问题标题】:How can I extract data from a list of parent objects with children?如何从具有子对象的父对象列表中提取数据?
【发布时间】:2016-09-30 13:01:34
【问题描述】:

如果我在列表中的类中有一个列表,其中类的定义如下:

class Class1
{
    public int Id { get; set; }

    public List<Class2> Class2s { get; set; }
}

class Class2
{
    public string Name { get; set; }

    public string Value { get; set; }
}

我可以创建一个Result 类型的列表,其中Result 是:

class Result
{
    public int Class1Id { get; set; }

    public string Name { get; set; }

    public string Value { get; set; }
}

请注意,Result 类包含来自 Class1Class2 的值。

像这样:

var results = new List<Result>();
foreach (var class1 in class1s) //class1s is a List of Class1
{
    foreach (var class2 in class1.Class2s)
    {
        results.Add(new Result()
        {
            Class1Id = class1.Id,
            Name = class2.Name,
            Value = class2.Value,
        };
    }
}

如何通过 linq 查询做到这一点?

我尝试了以下方法:

IList<Result> list = class1s.Select(c => c.Class2s.Select(c2 => new Result()
{
    Class1Id = c.Id,
    Type = c2.Type,
    Name = c2.Name,
}).ToList()).ToList();

但这失败并出现错误:

Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.List<Results>' to 'System.Collections.Generic.IList<Results>'. An explicit conversion exists (are you missing a cast?)

注意:

重复项没有回答问题,因为当结果列表是内部类列表并使用内部类的属性时,它们没有解决问题。

【问题讨论】:

  • @CodeCaster 当属性之一在外部类而不是列表中时,我应该如何使用 SelectMany 做到这一点?
  • 我建议您编辑标题和问题以说明您希望包含来自父对象的数据。事实上,“如何展平列表列表”的直接答案是“使用 SelectMany”。代码中丢失了一个重要的区别
  • 您也没有列表列表,您有父对象和子对象的列表。
  • @PanagiotisKanavos 编辑好点了吗?我在想出一个标题时遇到了麻烦,因此感谢您提供任何帮助

标签: c# linq


【解决方案1】:

使用两个from 语句,可以轻松地以查询格式从父母和孩子列表中检索数据

var results = from parent in class1s
              from child in parent.Class2s 
              select new Result {
                    Class1Id = parent.Id,
                    Name = child.Name,
                    Value = child.Value,
              };
var list=results.ToList();

在fluent格式中,可以使用SelectMany

var list = class1s.SelectMany(parent => parent.Class2s,
                              (parent,child)=>
                                           new Result {
                                              Class1Id = parent.Id,
                                              Name = child.Name,
                                              Value = child.Value
                                          }
           ).ToList();

出于显而易见的原因,我更喜欢第一种形式

请注意,我使用了接受结果选择器的SelectMany 重载。如果没有它,我将不得不在第一个选择器函数中使用Select,从而导致代码更加繁琐

【讨论】:

  • 其他格式可以轻松完成吗(不记得名字了)?
  • 不是容易,这就是为什么我要先尝试它。此外,它们是等价的
  • 我知道它们是等价的我只是个人更喜欢其他格式但感谢您的帮助
  • @TheLethalCoder 在这种情况下你会同意这不是最优雅的形式
【解决方案2】:

您可以使用以下方式以非查询格式执行此操作:

results = class1s.SelectMany(c => c.Class2s.Select(c2 => new Result()
        {
            Class1Id = c.Id,
            Name = c2.Name,
            Value = c2.Value,
        })).ToList();

请注意,这与您最初的尝试非常相似,但在class1s 上使用SelectMany 而不是Select

【讨论】:

  • 不需要双重选择,SelectMany 有一个接受结果选择器的覆盖。
  • 这是一个很好的观点@PanagiotisKanavos。我将把它留在这里作为一种替代方法,但赞成你的答案,因为它更全面。
  • 我也开始写 this 版本,但后来想起有时会出现意想不到的重载,让事情变得简单很多
  • 我太依赖于 OP 的原始代码 - 这会教我急于回答 :)
猜你喜欢
  • 2020-09-11
  • 2018-12-02
  • 2015-03-08
  • 2021-04-12
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 2011-09-07
  • 2021-11-26
相关资源
最近更新 更多