[英]Javascript - Efficient way to get distinct values from an array of objects
[英]Efficient way to delete from an array of objects in JavaScript
frontendtasks = [
{"id": 1, "name": "User Deletion", "script": "UserDeletion"},
{"id": 2, "name": "User Creation", "script_name": "UserCreation"}
]
backendtasks = [
{"id": 1, "name": "User Deletion", "script": "UserDeletion_V2"}
]
我正在尝试删除 frontendtask 中 id = 1 的条目,并使用此代码从 backendtask 中推送该条目。
if (backendtasks != 0) {
for (updated_task in backendtasks ) {
for (oldtask in frontendtasks) {
if (frontendtasks[oldtask].id == backendtasks[updated_task].id) {
frontendtasks[oldtask] = backendtasks[updated_task]
delete backendtasks[updated_task];
break;
}
}
}
for (new_task in backendtasks) {
frontendtasks.unshift(backendtasks[new_task])
}
}
这真的很慢,CPU 在浏览器中达到 100%,有 700 个项目。 有没有有效的方法来实现这个?
不要遍历两个 arrays,而是使用 object 到 map 后端 ID 值:
const mappings = {};
for (const task of backendtasks) {
mappings[task.id] = task;
}
for (let i = 0; i < frontendtasks.length; i ++) {
const curid = frontendtasks[i].id;
if (curid in mappings) {
frontendtasks[i] = mappings[curid];
delete mappings[curid];
}
}
// push is faster than unshift
for (const key in mappings) {
frontendtasks.push(mappings[key]);
}
方法:由于您有 2 个 arrays,我建议首先将后端数组规范化为 object,然后迭代前端数组并在规范化的 object 中查找,因为与数组中的 O(n) 相比,object 中的查找为 O(1)。
function getFrontendTasks(){ const frontendtasks = [ {"id": 1, "name": "User Deletion", "script": "UserDeletion"}, {"id": 2, "name": "User Creation", "script_name": "UserCreation"} ] const backendtasks = [ {"id": 1, "name": "User Deletion", "script": "UserDeletion_V2"} ] const normalizedBackendTasks = backendtasks.reduce((acc, val) => ({...acc, [val.id]: val}), {}); const newFrontendTasks = frontendtasks.map((task) => normalizedBackendTasks[task.id] || task); return newFrontendTasks } console.log(getFrontendTasks())
通过删除非常昂贵的嵌套for
循环,创建映射表将时间复杂度从O(n^2)降低到O(n) 。
试试下面的代码:
const map = {};
backendtasks.forEach(bt => (map[bt.id] = bt));
frontendtasks.forEach((ft, idx) => {
if (map[ft.id]) {
frontendtasks[idx] = map[ft.id];
delete map[ft.id];
}
});
frontendtasks = frontendtasks.concat(Object.values(map));
map()
function,如下所示。这将返回具有新值的新数组。 如您所见,它需要一个数组、一个 id(这可以是任何东西和任何类型)和一个回调。
在数组中搜索id
并在找到时运行回调。 您想做的事情的有效方法。
在回调中,我在backendtasks
上使用find()
只是因为我需要找到具有相同id
(id: 1) 的项目。
找到后,它从backendtasks
返回该项目,然后通过在map()
function 中返回该值来完成 function。
所以,这应该是O(n) ,考虑到回调只运行一次,在我看来它是一个更优雅的多次使用解决方案。
const frontendtasks: any[] = [];
const backendtasks: any[] = [];
const fn = (arr: any[], id: number, callback: (removed: any) => any) => {
return arr.map((ft) => {
if (ft.id !== id) return ft;
else return callback(ft);
});
};
fn(frontendtasks, 1, (rm) => backendtasks.find((id) => rm.id === id));
frontendtasks = [
{"id": 1, "name": "User Deletion", "script": "UserDeletion"},
{"id": 2, "name": "User Creation", "script_name": "UserCreation"}
]
backendtasks = [
{"id": 1, "name": "User Deletion", "script": "UserDeletion_V2"}
]
我正在尝试删除 frontendtask 中 id = 1 的条目,并使用此代码从 backendtask 推送条目。
if (backendtasks != 0) {
for (updated_task in backendtasks ) {
for (oldtask in frontendtasks) {
if (frontendtasks[oldtask].id == backendtasks[updated_task].id) {
frontendtasks[oldtask] = backendtasks[updated_task]
delete backendtasks[updated_task];
break;
}
}
}
for (new_task in backendtasks) {
frontendtasks.unshift(backendtasks[new_task])
}
}
这真的很慢,在浏览器中 CPU 达到 100%,有 700 个项目。 有没有有效的方法来实现这一点?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.