
本文介绍一种高效、可扩展的方案,将多个结构相同的二维数组(如 [[key, val], ...])按首元素(支持数字、字符串或 date 对象)归并,生成每个 key 对应的扁平化组合数组。
本文介绍一种高效、可扩展的方案,将多个结构相同的二维数组(如 [[key, val], ...])按首元素(支持数字、字符串或 date 对象)归并,生成每个 key 对应的扁平化组合数组。
在实际开发中,常需将多个来源的键值型二维数组(例如来自不同 API 响应的 [id, value] 或 [date, metric] 数据)按首项(即“键”)对齐合并。原始实现使用 Map 是合理且原生高效的,但存在两个关键优化点:一是需确保相同 key 的所有子项严格按输入顺序拼接(而非去重),二是需兼容 Date 等非基本类型作为 key —— 此时直接用 item[0] 作 Map 键可能因对象引用不等导致匹配失败。
以下为推荐的纯原生、健壮、无依赖解决方案:
function mergeArrays(arrays) {
// 使用 WeakMap 不适用(key 非对象),改用 Map + 序列化 key(仅当需要支持 Date 等对象时)
const mergedMap = new Map();
for (const array of arrays) {
for (const item of array) {
const key = item[0];
// 关键:若 key 是 Date,用 getTime() 保证可比性;其他类型直接使用
const serializableKey = key instanceof Date ? key.getTime() : key;
if (!mergedMap.has(serializableKey)) {
mergedMap.set(serializableKey, [key]); // 保留原始 key(如 Date 实例),非序列化值
}
// 从索引 1 开始追加后续元素,保持原始顺序
mergedMap.get(serializableKey).push(...item.slice(1));
}
}
return Array.from(mergedMap.values());
}
// 示例:支持 Date 类型 key
const today = new Date('2024-01-01');
const tomorrow = new Date('2024-01-02');
const arr1 = [[today, 'open'], [tomorrow, 'high']];
const arr2 = [[today, 'low'], [tomorrow, 'close']];
const arr3 = [[today, 'volume'], [tomorrow, 'change']];
console.log(mergeArrays([arr1, arr2, arr3]));
// 输出:
// [
// [2024-01-01T00:00:00.000Z, 'open', 'low', 'volume'],
// [2024-01-02T00:00:00.000Z, 'high', 'close', 'change']
// ]✅ 优势说明:
- 零依赖:不引入 Lodash,避免打包体积增加;
- 语义清晰:保留原始 key(如 Date 实例),而非字符串/时间戳;
- 顺序可靠:严格按输入数组顺序拼接值,避免 _.uniq() 导致意外去重或乱序;
- 类型安全:自动识别 Date 并转为 getTime() 用于 Map 键比较,兼顾性能与正确性;
- 可扩展:轻松适配三元组 [[key, a, b]] 或更长结构,slice(1) 自动提取全部附加值。
⚠️ 注意事项:
- 若输入数组中同一 key 出现多次(如 [[1,'X'],[1,'Y']]),本方案会按出现顺序累积所有值;如需覆盖逻辑,可改为 mergedMap.get(serializableKey).splice(1, Infinity, ...item.slice(1));
- 确保所有数组中对应 key 的数据结构一致(即 item.length ≥ 2),否则 slice(1) 可能返回空数组;
- 在极端大数据量场景(>10万项),可考虑预排序后双指针归并以降低时间复杂度,但日常业务中 Map 方案已足够高效(O(n))。
该方案兼顾简洁性、健壮性与工程实践,是处理多源键值数组对齐合并的理想选择。

















