JavaScript 中更快的' find & reorder'逻辑



我正在使用以下递归函数对树结构的某个级别的节点重新排序。使用排序重新排序不需要花费时间,但是递归地查找父节点需要花费时间。我怎样才能使这个更快呢?

const reorderNodes = (tree, reorderedObject) => {
let copy = cloneDeep(tree);
// reorder
const reorder = (children) =>
children?.slice().sort((a, b) => {
return (
reorderedObject.children.findIndex(reordered => reordered.id === a.id) -
reorderedObject.children.findIndex(reordered => reordered.id === b.id)
);
});
if (!reorderedObject.parentId) {
// if no parent
copy = reorder(copy);
} else {
// look recursively      
copy = copy.map(el => {
// found element to reorder.
if (el.children) {
if (el.id === reorderedObject.parentId) {
el.children = reorder(el.children);
} else {
el.children = reorderNodes(el.children, reorderedObject);
}
}
return el;
});
}
return copy;
};

树数据
const tree = [
{
id: 'module-1',
label: 'Unit',
children: [{ id: 'field-zz', label: 'Name' }]
},
{
id: 'module-2',
label: 'Plans',
children: [
{
id: 'level-1',
label: 'Test-Level-1',
children: [
{
id: 'level-1-1',
label: 'Test-Level-1-1',
children: [
{
id: 'field-1-1',
label: 'ID',
},
{
id: 'field-1-2',
label: 'First upd',
}
]
},
{
id: 'level-1-2',
label: 'Level-1-1-2',
children: [
{
id: 'field-2-1',
label: 'ID',

},
{
id: 'field-2-2',
label: 'First Upd',

}
]
}
]
},
{
id: 'level-2',
label: 'Test-Level-2',

children: [
{
id: 'field-3',
label: 'Keyword',

},
{
id: 'field-4',
label: 'Assignment',

}
]
},
{
id: 'module-3',
label: 'Find more',

children: [
{
id: 'field-5',
label: 'Description',

},
{
id: 'field-6',
label: 'ID',

}
]
}
]
},
{
id: 'module-4',
label: 'Data',

children: [
{ id: 'field-33333', label: 'Date'},
{ id: 'field-44444', label: 'Time'}
]
}
];

reorderedObject

const reorderedObject = {
parentid: 'module-4',

children: [
{ id: 'field-44444', label: 'Time'},
{ id: 'field-33333', label: 'Date'}
]
}

如果我有4个关卡深度和50个项目在每个关卡,需要10秒的处理。

您的代码应该很快。我家族树的递归下降语法分析器实现应用程序类似于你正在做的事情,从来没有超过几十毫秒画整个家族树。

你的代码的主要问题是:
let copy = cloneDeep(tree);

这是javascript引擎需要在后台做的一大堆malloc()!为了提高速度,避免在任何语言中复制内存。

如果您需要原始树,则只需克隆一次在输入递归函数之前。

你只需要执行一个图搜索,一旦你找到了有问题的节点,排序它的子节点。

由于sort()操作将数组排序到位,因此不需要所有slice()map()操作。你递归地复制树的每一层多次,你已经克隆了整个树开始。

我已经将图搜索操作实现为深度优先搜索:

const reorderNodes = (tree, reorderedObject) => {
const reorder = (nodes) => nodes.sort((a, b) => 
reorderedObject.children.findIndex(reordered => reordered.id === a.id) -
reorderedObject.children.findIndex(reordered => reordered.id === b.id)
);
const find = (nodes) => {
if (!reorderedObject.parentId) return nodes;
for (const node of nodes) {
if (node.children) {
if (node.id === reorderedObject.parentId) return node.children;

const result = find(node.children);
if (result) return result;
}
}
}
const copy = structuredClone(tree);
const found = find(copy);
reorder(found);
return copy;
};
const tree = [{
id: 'module-1',
label: 'Unit',
children: [{
id: 'field-zz',
label: 'Name'
}]
}, {
id: 'module-2',
label: 'Plans',
children: [{
id: 'level-1',
label: 'Test-Level-1',
children: [{
id: 'level-1-1',
label: 'Test-Level-1-1',
children: [{
id: 'field-1-1',
label: 'ID',
},
{
id: 'field-1-2',
label: 'First upd',
}
]
}, {
id: 'level-1-2',
label: 'Level-1-1-2',
children: [{
id: 'field-2-1',
label: 'ID',
}, {
id: 'field-2-2',
label: 'First Upd',
}]
}]
}, {
id: 'level-2',
label: 'Test-Level-2',
children: [{
id: 'field-3',
label: 'Keyword',
}, {
id: 'field-4',
label: 'Assignment',
}]
}, {
id: 'module-3',
label: 'Find more',
children: [{
id: 'field-5',
label: 'Description',
}, {
id: 'field-6',
label: 'ID',
}]
}]
}, {
id: 'module-4',
label: 'Data',
children: [{
id: 'field-33333',
label: 'Date'
}, {
id: 'field-44444',
label: 'Time'
}]
}];
const reorderedObject = {
parentId: 'module-4',
children: [{
id: 'field-44444',
label: 'Time'
}, {
id: 'field-33333',
label: 'Date'
}]
};
console.log(reorderNodes(tree, reorderedObject));

最新更新