【问题标题】: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 操作或不同的集合类型?

【问题讨论】:

    标签: c# arrays 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-08
        • 2021-10-04
        • 2022-10-05
        • 2021-03-29
        • 2018-04-11
        • 2017-08-25
        • 1970-01-01
        相关资源
        最近更新 更多