【问题标题】:How can I use LINQ to project this parent and children object model into a flat, single object?如何使用 LINQ 将此父子对象模型投影到一个平面的单个对象中?
【发布时间】:2011-09-08 01:37:08
【问题描述】:

我正在尝试将具有父 + 子数组的简单类扁平化为单个类。

发件人:

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<PewPew> PewPews { get; set; }
}

public class PewPew
{
    public string Name { get; set; }
    public string Whatever { get; set; }
}

- 1 | Fred | { { AAA | xxx }, { BBB | yyy } }
- 2 | Bill | { { CCC | zzz } }

收件人:

public class FooProjection
{
    public int Id { get; set; }
    public string Name { get; set; }
    public PewPewName { get; set; }
    public PewPewWhatever { get; set; }
}

- 1 | Fred | AAA | xxx
- 1 | Fred | BBB | yyy
- 2 | Bill | CCC | zzz

【问题讨论】:

    标签: c# .net linq linq-to-objects


    【解决方案1】:

    纯 Linq 方法

    您可以使用SelectMany() 重载,它允许您指定在集合中的每个元素上调用的结果选择器:

    将序列的每个元素投影到一个 IEnumerable,展平 将结果序列合并为一个序列,并调用结果选择器 作用于其中的每个元素。

    List<Foo> foos = new List<Foo>();
    var fooProjections = foos.SelectMany(x => x.PewPews, (foo, pew) => new FooProjection() 
    { 
        Id = foo.Id, 
        Name = foo.Name,
        PewPewName = pew.Name,
        PewPewWhatever = pew.Whatever 
    }).ToList();
    

    这种方法是最简洁的,但需要一些时间来适应,尤其是在您没有经常使用 Linq 的情况下。

    编辑:

    根据@AS-CII 的评论,仅使用循环和Select() 的简单投影可能更容易理解(这对于维护代码库很重要)。如果有人在这种情况下对 Linq 有任何问题,那么两个嵌套循环也可以。为了完整起见,我将两者都显示。

    使用 foreach 循环和 Select 投影

    只需遍历所有 Foos 并为当前项目中的每个 PewPew 创建一个新的 FooProjection。将它们全部添加到范围内的fooProjections 列表中。这种方法使用 Linq 投影从每个 PewPew 映射到 FooProjection,使用来自 foreach 循环的 foo

    List<Foo> foos = new List<Foo>();
    List<FooProjection> fooProjections = new List<FooProjection>();
    
    foreach(var foo in foos)
    {
        var someFooProjections = foo.PewPews.Select(x => new FooProjection() 
        { 
            Id = foo.Id, 
            Name = foo.Name, 
            PewPewName = x.Name, 
            PewPewWhatever = x.Whatever 
        });
        fooProjections.AddRange(someFooProjections);
    }
    

    使用两个嵌套的 foreach 循环

    只需使用两个 foreach 循环,外部迭代 Foos,内部迭代当前 foo 中的 PewPews 集合 - 将新的 FooProjection 添加到范围内的 fooProjections 列表中。这种方法根本不使用 Linq。

    List<FooProjection> fooProjections = new List<FooProjection>();
    foreach (var foo in foos)
        foreach (var pew in foo.PewPews)
        {
            fooProjections.Add(new FooProjection()
            {
                Id = foo.Id,
                Name = foo.Name,
                PewPewName = pew.Name,
                PewPewWhatever = pew.Whatever
            });
        }
    

    【讨论】:

    • 向他展示“更多单词”的做法。它更干净,更容易理解:)
    • @BrokenGlass 冗长的方式也很好(比较),但我也很喜欢。如果某些 Foo 的 PewPews 属性为空,会发生什么?
    • 添加了与纯 linq 的比较,一个 foreach 循环和两个嵌套的 foreach 循环
    • 全LINQ版本很容易理解,你只需要了解LINQ。必须分解它就像说向他展示'更多单词'的方式并将其分解为 IL 代码,然后是汇编......有效的概念,但在这种情况下,我会说 LINQ 很好;你必须学习语言。
    【解决方案2】:

    我发现具有多个froms 的查询表达式比调用SelectMany 更容易编写。它们编译成相同的东西。

    List<Foo> foos = GetFoos();
    
    var projected = 
        from foo in foos
        from pewPew in foo.PewPews
        select new FooProjection
            { Id = foo.Id, 
              Name = foo.Name, 
              PewPewName = pewPew.Name, 
              PewPewWhatever = pewPew.Whatever };
    

    【讨论】:

    • 这也很漂亮,实际上 :) LIKE!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    相关资源
    最近更新 更多