如何使用Linq将此父级和子级对象模型投影到平坦的单个对象中?

Pur*_*ome 7 .net c# linq linq-to-objects

我试图将一个包含父+子数组的简单类压缩成一个类.

从:

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 } }
Run Code Online (Sandbox Code Playgroud)

至:

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
Run Code Online (Sandbox Code Playgroud)

Bro*_*ass 13

纯粹的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();
Run Code Online (Sandbox Code Playgroud)

这种方法最简洁,但需要一些时间来适应,特别是如果你没有与Linq合作很多.

编辑:

根据@ AS-CII的评论,它可能更容易理解(这对维护代码库很重要)只需使用循环和简单的投影Select().如果有人在这个场景中遇到Linq问题,那么两个嵌套循环也会这样做.我将展示两者的完整性.

使用foreach循环和Select投影

只需遍历所有Foos并FooProjectionPewPew当前项目中的每个创建一个新的.将所有这些添加到fooProjections范围内的列表中.这种方法使用Linq投影使用foreach循环从每个映射PewPew到a 映射.FooProjectionfoo

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);
}
Run Code Online (Sandbox Code Playgroud)

使用两个嵌套的foreach循环

只需使用两个foreach循环,外部迭代在Foos上,内部覆盖当前foo中的PewPews集合 - 在范围内FooProjectionfooProjections列表中添加一个新的循环.这种方法根本没有使用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
        });
    }
Run Code Online (Sandbox Code Playgroud)


Aak*_*shM 6

我发现多个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 };
Run Code Online (Sandbox Code Playgroud)