
在前端开发中,我们经常会遇到需要对从后端获取的扁平数据进行复杂排序和结构化展示的场景。一个典型的例子是,数据项之间存在父子层级关系,同时每个数据项还有自己的显示优先级。本教程将以一个具体的案例为例,展示如何根据id、reference_id和display_priority这三个字段,对一个包含商品sku信息的数组进行重排序。
我们的目标是将一个初始的扁平数组:
[
{ id: 3, name: 'hello world', reference_id: null, display_priority: 10},
{ id: 6, name: 'hello world', reference_id: 2 , display_priority: 30},
{ id: 1, name: 'hello world', reference_id: 2, display_priority: 40 },
{ id: 4, name: 'hello world', reference_id: null, display_priority: 80},
{ id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
{ id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
]重排为以下结构:
[
{ id: 3, name: 'hello world', reference_id: null, display_priority: 10 },
{ id: 5, name: 'hello world', reference_id: 3, display_priority: 110 }, // id 5 是 id 3 的子项
{ id: 4, name: 'hello world', reference_id: null, display_priority: 80 },
{ id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
{ id: 6, name: 'hello world', reference_id: 2, display_priority: 30}, // id 6 是 id 2 的子项
{ id: 1, name: 'hello world', reference_id: 2, display_priority: 40}, // id 1 是 id 2 的子项
]重排规则如下:
在处理这类问题时,开发者可能会尝试使用 Array.prototype.reduce() 方法来迭代构建新数组。例如,原始问题中提供了一个尝试:
立即学习“Java免费学习笔记(深入)”;
const reorderedArray = test.reduce((acc, current) => {
const referenceId = current.reference_id;
if (referenceId === null) {
// 尝试插入父项
const referencedChildIndex = acc.findIndex(item => item.reference_id === current.id);
if (referencedChildIndex !== -1) {
acc.splice(referencedChildIndex, 0, current);
} else {
acc.push(current);
}
} else {
// 尝试插入子项
const referencedIndex = acc.findIndex(item => item.id === referenceId);
if (referencedIndex !== -1) {
acc.splice(referencedIndex + 1, 0, current);
} else {
acc.push(current);
}
}
return acc;
}, []);这种方法存在几个主要局限性:
为了克服这些局限性,我们需要一个更结构化、分阶段处理的策略。
一个更健壮的方法是首先识别所有父项和子项,构建它们之间的关系,然后根据优先级进行排序,最后将它们组装成最终的有序数组。
首先,我们需要遍历原始数组,将所有项目区分为顶级父项和子项。同时,为了方便查找,我们可以将子项按其 reference_id(即父项的 id)进行分组。
在将所有项目组合起来之前,我们首先需要确保顶级父项之间的顺序是正确的。根据需求,顶级父项应根据它们的 display_priority 字段进行升序排序。
这是将所有排序好的父项和子项组合在一起的最后一步。
/**
* 根据 reference_id 和 display_priority 重排数组。
*
* @param {Array<Object>} data 原始数组,每个对象包含 id, reference_id, display_priority 字段。
* @returns {Array<Object>} 重排后的数组。
*/
function reorderArrayByHierarchyAndPriority(data) {
const parents = []; // 存储所有顶级父项 (reference_id: null)
const childrenMap = new Map(); // 存储子项,键为父项id,值为子项数组
// 步骤1:数据分类与预处理
data.forEach(item => {
if (item.reference_id === null) {
parents.push(item);
} else {
if (!childrenMap.has(item.reference_id)) {
childrenMap.set(item.reference_id, []);
}
childrenMap.get(item.reference_id).push(item);
}
});
// 步骤2:父节点排序
// 顶级父项按 display_priority 升序排序
parents.sort((a, b) => a.display_priority - b.display_priority);
const reorderedArray = [];
// 步骤3:构建最终有序数组
// 遍历排序后的父项,并插入其子项
parents.forEach(parent => {
reorderedArray.push(parent); // 添加父项
// 检查是否有子项
if (childrenMap.has(parent.id)) {
let children = childrenMap.get(parent.id);
// 子项也按 display_priority 升序排序
children.sort((a, b) => a.display_priority - b.display_priority);
reorderedArray.push(...children); // 添加排序后的子项
}
});
return reorderedArray;
}
// 示例数据
const productSkus = [
{ id: 3, name: 'hello world', reference_id: null, display_priority: 10},
{ id: 6, name: 'hello world', reference_id: 2 , display_priority: 30},
{ id: 1, name: 'hello world', reference_id: 2, display_priority: 40 },
{ id: 4, name: 'hello world', reference_id: null, display_priority: 80},
{ id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
{ id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
];
const result = reorderArrayByHierarchyAndPriority(productSkus);
console.log(result);
/*
预期输出:
[
{ id: 3, name: 'hello world', reference_id: null, display_priority: 10 },
{ id: 5, name: 'hello world', reference_id: 3, display_priority: 110 },
{ id: 4, name: 'hello world', reference_id: null, display_priority: 80 },
{ id: 2, name: 'hello world', reference_id: null, display_priority: 100 },
{ id: 6, name: 'hello world', reference_id: 2, display_priority: 30 },
{ id: 1, name: 'hello world', reference_id: 2, display_priority: 40 }
]
*/reorderArrayByHierarchyAndPriority(data) 函数:
数据分类 (data.forEach(...)):
父节点排序 (parents.sort(...)):
**构建最终数组 (`parents
以上就是JavaScript数组复杂排序:实现父子层级与优先级双重排序的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号