让我们假设有一些类:
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 查询中完成(例如作为另一个更复杂的单个查询的一部分查询)。
请您参考如下方法:
为什么不用最简单的方法呢?我认为 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();
