You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript合并同ID对象,生成对应小时的时间数组?

问题描述

我有一组包含id和time(小时数值)的对象数组,尝试遍历每个对象生成对应24小时的数组:匹配小时则填入对应time值,否则填0。但当前代码会为每个对象生成新条目,无法合并相同id的结果。

当前代码

let formatted = [];

const results = [
  { id: "id1", time: 4 },
  { id: "id1", time: 5 },
  { id: "id2", time: 1 },
  { id: "id2", time: 15 },
  { id: "id2", time: 12 },
  { id: "id3", time: 6 },
  { id: "id3", time: 8 },
];

const hours = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, ];

results.forEach((result) => {
  let hourArr = [];

  hours.forEach((hour) => {
    hourArr.push(result.time == hour ? hour : 0);
  });

  formatted.push({ id: result.id, time: hourArr });
});

console.log(formatted);

当前输出

[
  {
    id: "id1",
    time: [
      0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id1",
    time: [
      0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id2",
    time: [
      0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id2",
    time: [
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id2",
    time: [
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id3",
    time: [
      0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id3",
    time: [
      0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
];

期望输出

将相同id的对象合并,生成一个包含24小时的数组,对应小时位置填入该id的time值,其余为0:

[
  {
    id: "id1",
    time: [
      0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id2",
    time: [
      0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
  {
    id: "id3",
    time: [
      0, 0, 0, 0, 0, 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ],
  },
];
解决方案

核心思路是先按id聚合同一id的所有time值,再为每个id生成完整的24小时数组,或者直接在遍历过程中维护每个id的结果数组。

方法一:先分组再生成结果

const results = [
  { id: "id1", time: 4 },
  { id: "id1", time: 5 },
  { id: "id2", time: 1 },
  { id: "id2", time: 15 },
  { id: "id2", time: 12 },
  { id: "id3", time: 6 },
  { id: "id3", time: 8 },
];

const hours = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];

// 按id分组,收集每个id对应的所有time值
const groupedData = {};
results.forEach(item => {
  if (!groupedData[item.id]) {
    groupedData[item.id] = [];
  }
  groupedData[item.id].push(item.time);
});

// 为每个分组生成24小时数组
const formatted = Object.entries(groupedData).map(([id, times]) => {
  const timeArr = hours.map(hour => times.includes(hour) ? hour : 0);
  return { id, time: timeArr };
});

console.log(formatted);

方法二:用reduce一步完成(更高效)

const results = [
  { id: "id1", time: 4 },
  { id: "id1", time: 5 },
  { id: "id2", time: 1 },
  { id: "id2", time: 15 },
  { id: "id2", time: 12 },
  { id: "id3", time: 6 },
  { id: "id3", time: 8 },
];

const formatted = results.reduce((acc, item) => {
  // 查找当前id是否已存在于结果数组中
  const existingEntry = acc.find(entry => entry.id === item.id);
  if (existingEntry) {
    // 存在则直接更新对应小时的位置
    existingEntry.time[item.time] = item.time;
  } else {
    // 不存在则初始化全0数组,再设置对应小时值
    const timeArr = new Array(24).fill(0);
    timeArr[item.time] = item.time;
    acc.push({ id: item.id, time: timeArr });
  }
  return acc;
}, []);

console.log(formatted);

代码说明

  • 方法一先通过对象完成分组,再遍历分组数据生成结果,逻辑清晰易读;
  • 方法二利用reduce直接在遍历原数组时维护结果数组,减少一次遍历操作,性能更优,适合数据量较大的场景。

内容的提问来源于stack exchange,提问作者Irving Real

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:22:55