JavaScript 迭代和访问项目的性能
JavaScript performance for iterating and accessing items
我有一个项目数组,有时需要迭代这些项目,有时需要直接访问其中的一个成员。所以我决定在两个变量中保留引用,一个数组和一个对象。我这样做:
const itemsArr = [];
const itemsObj = {};
const addItem = (data) => {
const item = {
id: data.id,
name: data.name
};
itemsArr.push(item);
itemsObj[data.id] = item;
}
const removeItem = (data) => {
let i;
for (i = 0; i < itemsArr.length; i++) {
if (itemsArr[i].id === data.id) {
itemsArr.splice(i, 1);
break;
}
}
itemsObj[data.id] = null;
delete itemsObj[data.id];
}
const getWithId = (id) => {
return itemsObj[id];
}
const getWithName = (name) => {
let i;
for (i = 0; i < itemsArr.length; i++) {
if (itemsArr[i].name === name) {
return itemsArr[i];
}
}
return null
}
所以我管理两个对象并根据任务使用一个或另一个,我觉得这是最高效的方法,但也许有更好的方法,比如 Map 或 Set。
是否有一个 JavaScript 数据结构在迭代中优于数组和在查找中优于对象?
我认为 Object.keys
迭代一个对象有额外的性能成本,类似地 Array.filter
对数组的查找,所以我的直觉是使用数组进行迭代和对象进行查找,但是如果有是为两者优化的单一数据结构,我想知道并在我的代码中只使用一个 items
。
谢谢
首先,对于 lookup-by-id 部分,我建议使用 Map
,而不是对象。对象针对常见的编程用例进行了优化,在这些用例中,它们的属性集随着时间的推移相当一致(值可能会改变,但对象的 shape [它具有的属性] 大多数情况下不会'吨)。 Map
作为通用 name/value 商店进行了优化,可以更好地处理该用例。更多内容在 on this MDN page.
Is there a single Javascript data structure that will outperform arrays in iteration and objects in lookup?
不,但是 Map
和数组之间的迭代速度差异在 广大 大多数应用程序中无关紧要。是的,在大多数情况下数组会更快(这在一定程度上取决于数组的构建方式),但这真的不太重要。
但是,如果您只通过 id
或 name
访问,则您无论如何都不会进行迭代。您可能需要两个映射而不是一个映射和一个数组,因为无论哪种方式查找项目都是次线性的而不是线性的。它还使代码更简单:
const itemsByName = new Map();
const itemsById = new Map();
const addItem = (data) => {
const item = {
id: data.id,
name: data.name
};
itemsByName.set(data.name, data);
itemsByid.set(data.id, data);
};
const removeItem = (data) => {
itemsByName.delete(data.name);
itemsByid.delete(data.id);
};
const getWithId = (id) => {
return itemsById.get(id);
};
const getWithName = (name) => {
return itemsByName.get(name);
};
FWIW,如果上面没有 itemsByName
因为你不需要 name
查找是次线性的,下面是 getWithName
的代码使用 itemsById
:
const getWithName = (name) => {
for (const item of itemsById.values()) {
if (data.name === name) {
return data;
}
}
return null;
};
我有一个项目数组,有时需要迭代这些项目,有时需要直接访问其中的一个成员。所以我决定在两个变量中保留引用,一个数组和一个对象。我这样做:
const itemsArr = [];
const itemsObj = {};
const addItem = (data) => {
const item = {
id: data.id,
name: data.name
};
itemsArr.push(item);
itemsObj[data.id] = item;
}
const removeItem = (data) => {
let i;
for (i = 0; i < itemsArr.length; i++) {
if (itemsArr[i].id === data.id) {
itemsArr.splice(i, 1);
break;
}
}
itemsObj[data.id] = null;
delete itemsObj[data.id];
}
const getWithId = (id) => {
return itemsObj[id];
}
const getWithName = (name) => {
let i;
for (i = 0; i < itemsArr.length; i++) {
if (itemsArr[i].name === name) {
return itemsArr[i];
}
}
return null
}
所以我管理两个对象并根据任务使用一个或另一个,我觉得这是最高效的方法,但也许有更好的方法,比如 Map 或 Set。
是否有一个 JavaScript 数据结构在迭代中优于数组和在查找中优于对象?
我认为 Object.keys
迭代一个对象有额外的性能成本,类似地 Array.filter
对数组的查找,所以我的直觉是使用数组进行迭代和对象进行查找,但是如果有是为两者优化的单一数据结构,我想知道并在我的代码中只使用一个 items
。
谢谢
首先,对于 lookup-by-id 部分,我建议使用 Map
,而不是对象。对象针对常见的编程用例进行了优化,在这些用例中,它们的属性集随着时间的推移相当一致(值可能会改变,但对象的 shape [它具有的属性] 大多数情况下不会'吨)。 Map
作为通用 name/value 商店进行了优化,可以更好地处理该用例。更多内容在 on this MDN page.
Is there a single Javascript data structure that will outperform arrays in iteration and objects in lookup?
不,但是 Map
和数组之间的迭代速度差异在 广大 大多数应用程序中无关紧要。是的,在大多数情况下数组会更快(这在一定程度上取决于数组的构建方式),但这真的不太重要。
但是,如果您只通过 id
或 name
访问,则您无论如何都不会进行迭代。您可能需要两个映射而不是一个映射和一个数组,因为无论哪种方式查找项目都是次线性的而不是线性的。它还使代码更简单:
const itemsByName = new Map();
const itemsById = new Map();
const addItem = (data) => {
const item = {
id: data.id,
name: data.name
};
itemsByName.set(data.name, data);
itemsByid.set(data.id, data);
};
const removeItem = (data) => {
itemsByName.delete(data.name);
itemsByid.delete(data.id);
};
const getWithId = (id) => {
return itemsById.get(id);
};
const getWithName = (name) => {
return itemsByName.get(name);
};
FWIW,如果上面没有 itemsByName
因为你不需要 name
查找是次线性的,下面是 getWithName
的代码使用 itemsById
:
const getWithName = (name) => {
for (const item of itemsById.values()) {
if (data.name === name) {
return data;
}
}
return null;
};