扁平化数组对象

Posted

技术标签:

【中文标题】扁平化数组对象【英文标题】:Flattening object of arrays 【发布时间】:2021-12-05 10:36:59 【问题描述】:

我有一个由一个 ID 和两个数组组成的“Compact”对象:

public class Compact
    
        public int Id  get; set; 
        public int[] Number  get; set; 
        public double[] Value  get; set; 

        public Compact(int id, int[] number,  double[] value)
        
            Id = id;
            Number = number;
            Value = value;
        
    

Compact 对象的列表可以这样初始化:

List<Compact> c = new List<Compact>
        
            new Compact(1, new int[]  1, 2, 3 , new double[]  0.05, 0.02, 0.03 ),
            new Compact(2, new int[]  1, 2, 3 , new double[]  0.07, 0.01, 0.04 ),
            new Compact(3, new int[]  1, 2, 3 , new double[]  0.02, 0.025, 0.05 )
        ;

我正在寻找一种优雅的方式来将此对象展平为“展平”对象:

public class Flattened
    
        public int Id  get; set; 
        public int Number  get; set; 
        public double Value  get; set; 

        public Flattened(int id, int number, double value)
        
            Id = id;
            Number = number;
            Value = value;
        
    

展平的结果将对应于:

List<Flattened> f = new List<Flattened>
        
            new Flattened(1,1,0.05),
            new Flattened(1,2,0.02),
            new Flattened(1,3,0.03),
            new Flattened(2,1,0.07),
            new Flattened(2,2,0.01),
            new Flattened(2,3,0.04),
            new Flattened(3,1,0.02),
            new Flattened(3,2,0.025),
            new Flattened(3,3,0.05)
        ;

我可以使用循环进行展平,但我想知道在性能方面是否有更合适的方法,例如 Linq 操作或不同的集合类型?

【问题讨论】:

【参考方案1】:

您可以简单地运行for 循环。

List<Compact> ls = new List<Compact>

    new Compact(1, new int[]  1, 2, 3 , new double[]  0.05, 0.02, 0.03 ),
    new Compact(2, new int[]  1, 2, 3 , new double[]  0.07, 0.01, 0.04 ),
    new Compact(3, new int[]  1, 2, 3 , new double[]  0.02, 0.025, 0.05 )
;
List<Flattened> ls2 = new List<Flattened>();
foreach (Compact compact in ls)

    for (var index = 0; index < compact.Number.Length; index++)
    
        ls2.Add(new Flattened(compact.Id, compact.Number[index], compact.Value[index]));
    

注意我假设两个数组的项目数相同。

【讨论】:

嗨 Vivek,谢谢你的建议。这也是我自己最终的结果,但我希望会有一些很酷的 Linq 单线 :) 你认为这个循环在性能方面会好吗? 在时间复杂度方面优化了代码。如果您已经将其作为解决方案实施并提及您正在寻找更好的解决方案,您应该在问题中发布。酷和更少的代码行总是不是一个好的解决方案@MadsGeltingBech 是的,我的坏事会做!看看你将如何实现循环仍然很有用,谢谢。 @MadsGeltingBech 如果它回答了您最初发布的问题,您应该接受答案,如果您有其他问题,请发布新问题 很公平,我发布了一个新问题。【参考方案2】:

使用 LINQ,你可以做到

c.SelectMany(
    x => x.Number.Zip(x.Value, (n, v) => new Flattened(x.Id, n, v))
).ToList()

SelectMany 进行扁平化,Zip,顾名思义,将NumberValue 数组“压缩”在一起,并将函数(n, v) =&gt; new Flattened(x.Id, n, v) 应用于每一对,创建一个Flattened 对象来自每一对。

【讨论】:

【参考方案3】:

您可以为此使用 Linq,SelectManyZip 的组合应该可以解决问题

(n, v) =&gt; (n, v) 创建一个由 NumberValue 组成的元组

List<Compact> ls = new List<Compact>

    new Compact(1, new int[]  1, 2, 3 , new double[]  0.05, 0.02, 0.03 ),
    new Compact(2, new int[]  1, 2, 3 , new double[]  0.07, 0.01, 0.04 ),
    new Compact(3, new int[]  1, 2, 3 , new double[]  0.02, 0.025, 0.05 )
;

var flattened = ls
    .SelectMany(
        c => c.Number.Zip(c.Value, (n, v) => (n, v)),
        (c, nv) => new Flattened(c.Id, nv.n, nv.v)
    ).ToList();

dotnetfiddle

【讨论】:

以上是关于扁平化数组对象的主要内容,如果未能解决你的问题,请参考以下文章

关于ES6的flat(扁平化数组)

JavaScript 扁平与树形数组数据的转换

深拷贝和数组扁平化

JavaScript数组常用方法解析和深层次js数组扁平化

JavaScript 数据扁平化处理

JS:数组扁平化、去重、排序