Skip to main content
 首页 » 编程设计

c#之将对象集合解压缩到其属性数组中

2024年02月13日28qlqwjy

让我们假设有一些类:

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();