繁体   English   中英

从 JavaScript 中的对象数组中删除的有效方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM