![](/img/trans.png)
[英]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.