我们假设有一些类:
public class SomeClass
{
public string A;
public int B;
public double C;
}
我们有一个集合:
var list = new List<SomeClass>()
{
new SomeClass() { A = "A", B = 2, C = 4.0 },
new SomeClass() { A = "B", B = 6, C = 8.0 }
};
我们如何能够以最有效的方式将此集合转换为分别为A
,B
和C
的三个数组(或数组列表)?在这种情况下,它将是:
var Ar = new[] { "A", "B" };
var Br = new[] { 2, 6 };
var Cr = new[] { 4.0, 8.0 };
到目前为止,我有工作 LINQ查询:
var lists = list.SelectMany(c => new object[] { c.A, c.B, c.C })
.Select((v, i) => new { Index = i, Object = v})
.GroupBy(g => g.Index % 3, g => g.Object, (k,v) => v.ToArray())
.ToList();
但是我想知道我是否错过了一些明显的东西以及是否有可能做得很聪明,例如无需在SelectMany
内创建临时子集合。
编辑: 我的问题是从理论的角度来看 - 如果它可以在单个LINQ查询中完成(例如作为另一个的一部分,更复杂的单一查询)。
答案 0 :(得分:4)
为什么不以最简单的方式做到这一点?我认为3个单独的查询应该比SelectMany
+ GroupBy
解决方案更有效:
var Ar = list.Select(x => x.A).ToList();
var Br = list.Select(x => x.B).ToList();
var Cr = list.Select(x => x.C).ToList();
它只需要在list
集合上进行3次迭代。对于GroupBy
,您只有一次迭代,但源集合比list
长3倍,因此没有差异(因为SelectMany
)并且需要进行额外的GetHashCode
调用分组。
<强>更新强>
同一方法的单行版本:
var items = new [] {
list.Select(x => x.A).ToList(),
list.Select(x => x.B).ToList(),
list.Select(x => x.C).ToList()
}
更新2
如果您不想使用SelectMany
,则可以使用Concat
。但是,它还需要在GroupBy
中进行更改:
var lists = list.Select(c => c.A)
.Concat(list.Select(c => c.B))
.Concat(list.Select(c => c.C))
.Select((v, i) => new { Index = i, Object = v})
.GroupBy(g => g.Index / list.Count, g => g.Object, (k,v) => v.ToArray())
.ToList();