【问题标题】:Javascript runtime optimizing array modificationsJavascript 运行时优化数组修改
【发布时间】:2025-12-17 10:50:01
【问题描述】:

我在优化代码的运行时时遇到问题。理想情况下,我想要实现的是以下所有操作都在一个循环中执行,这样我就不必像现在这样多次运行数据集(非常大的数据集!)

代码将 aggData 转换为以下格式的数组:[0: 0, 1: 0, 2: 0, 3: 43, 4: 121, 5: 0, ....],其中每个数字代表区间中的一年,如果区间是(1800-2020),0代表1800的计数,1代表1801,依此类推..

aggData 是以下格式的对象数组:{key_as_string: "1900-01-01T00:00:00.000Z", key: -2208988800000, doc_count: 17}。 start-year 是 doc_count 大于 0 的第一年。

下面我将描述每个步骤的作用,就像现在的代码一样:

这里我将列表中每个对象的格式更改为:{year: number, count: number}

 const formatAggData = aggData
        .map((item: AggData) => {
            return { year: moment(item.key_as_string).year(), count: item.doc_count };
        });

此函数创建一个对象数组,其中 from 作为开始年份和 to 作为结束年份,如果年份已经存在于 existingArray 中,则使用从那里开始的计数,否则将计数设置为 0。

    function fillYears(from: number, to: number, existingArray: YearCount[]) {
        const existingObject: { [year: string]: number } = { year: null };
        existingArray.map((x: YearCount) => (existingObject[x.year] = x.count));

        const yearsArray = [];
        for (let i = from; i <= to; i++) {
            yearsArray.push({
                year: i,
                count: existingObject[i] || 0,
            });
        }

        return yearsArray;
    }

将年份值转换为计数值,其中列表中的第一年将是 0 对应的值,第二年将是 1 对应的值等等..

    const resultList = fillYears(min, max, formatAggData).map(
        (item: YearCount) => item.count,
    );

【问题讨论】:

  • "非常大的数据集!" - 数据来自哪里?您的代码的哪一部分实际上是缓慢的操作(您是否对其进行了分析)?此外,您的数据集似乎从来没有超过 220 个项目(从 1800 年到 2020 年),所以这不是“大”。
  • 数据是否按年份排序?在这种情况下,您根本不需要使用 existingObject 查找。
  • 抱歉没有提供足够的细节!数据是从 ElasticSearch 日期直方图聚合返回的,是的,数据按年份排序。 @Bergi

标签: javascript arrays optimization


【解决方案1】:

我在看你的代码。你不能这样吗?看起来你现在不需要知道年份

function fillYears(from: number, to:number, existingYears: YearCount[]) {
    for (let i = from; i <= to; i++) {
      yearsArray.push({
          year: i,
          count: existingYears[i].doc_count || 0,
      });
  }
}

【讨论】:

  • 是的,你是对的!非常感谢!我唯一需要改变的是:count: existingArray[i - from]?.count || 0,(因为from参数是年份而不是从0开始)