
在javascript开发中,我们经常需要处理包含多个对象的数组,并根据某个共同的键(如日期、id等)将这些对象合并为一个。这通常发生在数据聚合、转换或去重等场景。例如,您可能拥有多个描述同一日期事件的对象,但每个对象只包含部分信息,最终目标是将所有相关信息汇聚到该日期对应的单个对象中。
以下是本文将要处理的原始数据示例,其中包含按日期分散的多个对象:
const cleanedData = [{
data: {
hours: ["2"],
timeIn: ["2023-05-01T18:00:00Z"],
timeOut: ["2023-05-01T20:00:00Z"],
type: ["Client"]
},
date: "5/1/2023",
entries: 2
}, {
data: {
hours: [2, 2],
timeIn: ["2023-05-10T18:00:00Z", "2023-05-10T16:00:00Z"],
timeOut: ["2023-05-10T20:00:00Z", "2023-05-10T18:00:00Z"],
type: ["Client"]
},
date: "5/10/2023",
entries: 4
}, {
date: "5/1/2023",
visits: 2
}, {
date: "5/10/2023",
visits: 4
}, {
date: "5/1/2023",
miles: 20
}, {
date: "5/10/2023",
miles: 40
}];目标是将所有date相同的对象合并成一个,例如,"5/1/2023"对应的所有属性(data, entries, visits, miles)都集中到一个对象中。
一种常见的合并尝试是遍历数组,查找具有相同键(如date)的目标对象,然后将当前对象的属性复制到目标对象中。以下是原始代码片段,它试图实现此逻辑:
var merged = [];
cleanedData.forEach(function(item) {
var idx;
var found = merged.some(function(el, i) {
idx = el.date === item.date ? i : null;
return el.date === item.date;
});
if (!found) {
merged.push(item);
} else if (idx !== null) {
// 问题所在:for (k in Object.keys(item))
for (k in Object.keys(item)) {
if (item.hasOwnProperty(k)) {
merged[idx][k] = item[k];
}
}
}
});
// 结果未能包含 'visits' 和 'miles' 属性
// console.log(merged);这段代码的意图是,如果item.date在merged数组中已存在,则将item的属性合并到merged中对应的对象上。然而,执行后发现,包含visits和miles属性的对象并未被正确合并。
立即学习“Java免费学习笔记(深入)”;
问题根源在于for (k in Object.keys(item))这行代码。
为了遍历Object.keys(item)返回的属性名数组,应该使用for...of循环。for...of循环直接迭代可迭代对象的元素值,这正是我们需要的。此外,Object.keys()本身就只返回对象自身的、可枚举的属性,因此在遍历其结果时,通常不需要再额外使用hasOwnProperty进行检查。
// 修复后的代码片段
var merged = [];
cleanedData.forEach(function(item) {
var idx = -1; // 初始化为-1表示未找到
var found = merged.some(function(el, i) {
if (el.date === item.date) {
idx = i; // 找到匹配项时更新索引
return true;
}
return false;
});
if (!found) {
merged.push(item);
} else { // 确保 idx 已经被正确赋值
// 使用 for...of 遍历属性名
for (let k of Object.keys(item)) { // 使用 let 声明 k
// 无需 hasOwnProperty 检查,Object.keys() 已经过滤
merged[idx][k] = item[k];
}
}
});
console.log("修复后的结果 (原始方法):", merged);
/* 预期输出 (与 Map 方案相同):
[
{
data: {
hours: [ '2' ],
timeIn: [ '2023-05-01T18:00:00Z' ],
timeOut: [ '2023-05-01T20:00:00Z' ],
type: [ 'Client' ]
},
date: '5/1/2023',
entries: 2,
visits: 2,
miles: 20
},
{
data: {
hours: [ 2, 2 ],
timeIn: [ '2023-05-10T18:00:00Z', '2023-05-10T16:00:00Z' ],
timeOut: [ '2023-05-10T20:00:00Z', '2023-05-10T18:00:00Z' ],
type: [ 'Client' ]
},
date: '5/10/2023',
entries: 4,
visits: 4,
miles: 40
}
]
*/注意: 循环变量k应使用let或const声明,避免创建全局变量,这是一种良好的编程习惯。
上述修复虽然解决了原始问题,但其查找逻辑(merged.some)在每次迭代中都可能遍历merged数组,对于大型数据集效率不高(时间复杂度可能接近O(N^2))。
更推荐的方法是利用JavaScript的Map对象,它提供了一种高效的键值对存储,可以快速通过键查找对应的值(接近O(1)的查找时间)。结合Object.assign,我们可以实现更简洁、高效的合并逻辑。
const cleanedData = [{data: {hours: ["2"],timeIn: ["2023-05-01T18:00:00Z"],timeOut: ["2023-05-01T20:00:00Z"],type: ["Client"]},date: "5/1/2023",entries: 2}, {data: {hours: [2, 2],timeIn: ["2023-05-10T18:00:00Z", "2023-05-10T16:00:00Z"],timeOut: ["2023-05-10T20:00:00Z", "2023-05-10T18:00:00Z"],type: ["Client"]},date: "5/10/2023",entries: 4}, {date: "5/1/2023",visits: 2}, {date: "5/10/2023",visits: 4}, {date: "5/1以上就是JavaScript数组对象合并策略:避免常见陷阱与高效实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号