基于product_id合并对象并排序的JavaScript代码优化咨询
如何优化基于product_id合并大型对象并排序的JavaScript代码?
我有两个大型对象(为便于理解已简化示例),需要基于product_id将二者合并、提取所需属性,完成后进行排序,但当前实现耗时较长,请问该如何优化?
原实现代码
const productsList = { 27: { id: 2, limit: 4363614, initial_limit: '1', date: null, }, 59: { id: 13, limit: 757502, initial_limit: '1', date: null, }, 62: { id: 30, limit: 394878, initial_limit: '2', date: null, }, }; const updatingDataList = { updatedData: { '1INCHEQC': { open_value: 0.2834, high_value: 0.2954, prcing: 68357.32, volume: 237875, product_id: 59, }, '2INCHEQF': { open_value: 82.79, high_value: 88.54, low: 81.99, prcing: 62054.321, volume: 739, product_id: 62, }, '3INCHEQS': { open_value: 0.2806, high_value: 0.2975, prcing: 300550.43, volume: 1053694, product_id: 89, }, }, originalData: { 59: '23.123', 62: '3452.21', 89: '456.11', }, }; // 基于product_id合并两个对象 const productsListUpdatingDataListAndOriginalDataMergedObject = Object.keys( productsList )?.reduce((result, productId) => { const matchingUpdatingData = Object.values(updatingDataList.updatedData)?.find( item => item.product_id === parseInt(productId, 10) ); if (matchingUpdatingData) { // 提取productList中需要的属性 const { limit } = productsList[productId]; result[productId] = { limit, updated_data: { ...matchingUpdatingData, originalData: updatingDataList.originalData[productId] }, }; } return result; }, {}); // 排序处理 const sortedData = Object.values( productsListUpdatingDataListAndOriginalDataMergedObject )?.sort( (firstProduct, secondProduct) => secondProduct.updated_data.originalData - firstProduct.updated_data.originalData ); console.log(sortedData);
优化思路及方案
1. 预处理updatedData,构建product_id映射表
原代码中每次遍历productsList的key时,都要调用Object.values(updatingDataList.updatedData).find(),这是O(n)的重复遍历操作,当数据量大时时间复杂度会飙升至O(m*n)(m为productsList长度,n为updatedData长度)。
我们可以先把updatedData转换成以product_id为键的对象,后续查找直接通过键访问,时间复杂度降至O(1):
// 预处理生成product_id到对应数据的映射 const updatedDataMap = Object.values(updatingDataList.updatedData).reduce((map, item) => { map[item.product_id] = item; return map; }, {});
2. 简化合并逻辑,减少重复计算
利用预处理好的映射表,合并时直接通过product_id快速获取对应数据,避免重复遍历,同时把parseInt的操作提前,减少重复转换。
3. 显式转换排序字段类型
原排序逻辑中originalData是字符串类型,减法会隐式转换为数字,但显式转换为浮点数更清晰,也能避免潜在的类型错误。
优化后的完整代码
const productsList = { 27: { id: 2, limit: 4363614, initial_limit: '1', date: null, }, 59: { id: 13, limit: 757502, initial_limit: '1', date: null, }, 62: { id: 30, limit: 394878, initial_limit: '2', date: null, }, }; const updatingDataList = { updatedData: { '1INCHEQC': { open_value: 0.2834, high_value: 0.2954, prcing: 68357.32, volume: 237875, product_id: 59, }, '2INCHEQF': { open_value: 82.79, high_value: 88.54, low: 81.99, prcing: 62054.321, volume: 739, product_id: 62, }, '3INCHEQS': { open_value: 0.2806, high_value: 0.2975, prcing: 300550.43, volume: 1053694, product_id: 89, }, }, originalData: { 59: '23.123', 62: '3452.21', 89: '456.11', }, }; // 预处理updatedData,生成product_id映射表,O(n)时间 const updatedDataMap = Object.values(updatingDataList.updatedData).reduce((map, item) => { map[item.product_id] = item; return map; }, {}); // 合并数据,O(m)时间(m为productsList长度) const mergedObject = Object.keys(productsList).reduce((result, productId) => { const numProductId = parseInt(productId, 10); const matchingData = updatedDataMap[numProductId]; if (matchingData) { result[productId] = { limit: productsList[productId].limit, updated_data: { ...matchingData, originalData: updatingDataList.originalData[productId] } }; } return result; }, {}); // 排序,显式转换为浮点数,避免隐式转换问题 const sortedData = Object.values(mergedObject).sort((a, b) => { const numA = parseFloat(a.updated_data.originalData); const numB = parseFloat(b.updated_data.originalData); return numB - numA; }); console.log(sortedData);
优化效果说明
- 时间复杂度从原有的O(m*n + k log k)(k为合并后数据长度)降至O(n + m + k log k),在数据量较大时性能提升明显。
- 代码逻辑更清晰,减少了重复遍历和转换操作,显式类型转换也提升了代码可靠性。
内容的提问来源于stack exchange,提问作者dev
相关产品推荐
相关产品推荐

