我正试图将一个包含父+子数组的简单类压缩成一个类。
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
答案 0 :(得分:12)
您可以使用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问题,那么两个嵌套循环也会这样做。我将展示两者的完整性。
只需迭代所有Foos,并为当前项目中的每个FooProjection
创建一个新PewPew
。将所有这些添加到范围内的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
循环,外部迭代在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
});
}
答案 1 :(得分:5)
我发现多个from
的查询表达式比调用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 };