Javascript 什么';在一个大的对象数组中改变单个对象属性的最快方法是什么?
我正在我的应用程序中创建一个类似Reddit的投票系统。每个对象(线程)都有一个score属性和一个类似于父对象的对象数组(将其视为线程的注释)。Javascript 什么';在一个大的对象数组中改变单个对象属性的最快方法是什么?,javascript,reactjs,optimization,redux,react-redux,Javascript,Reactjs,Optimization,Redux,React Redux,我正在我的应用程序中创建一个类似Reddit的投票系统。每个对象(线程)都有一个score属性和一个类似于父对象的对象数组(将其视为线程的注释)。 以下是一个简化的示例: { id: '123fdx12c1', author: 'Anon', score: 1, users: [ { id: '321fdx12c1', name: 'anon', score: 1 }, { id: 'asd123f1fd1'
以下是一个简化的示例:
{
id: '123fdx12c1',
author: 'Anon',
score: 1,
users: [
{
id: '321fdx12c1',
name: 'anon',
score: 1
},
{
id: 'asd123f1fd1',
name: 'anon',
score: 1
}
]
}
现在想象一个像这样的大型对象阵列。每当用户投票时,都会发送一个具有正确id的操作,以查找匹配的id并更改分数值。我的做法:
case 'VOTE':
return state.map((question) => {
question.users = question.users.map((user) => {
if (user.id == action.id) {
return {
...user,
voteStatus: action.voteStatus,
score: action.score
}
}
return user;
});
if (question.id == action.id) {
return {
...question,
voteStatus: action.voteStatus,
score: action.score
}
}
return question;
});
它映射整个数组只是为了更改对象的一个属性。有更快的方法吗?我知道
.map
和.filter
由于各种原因(大部分是好的)很受欢迎。但有时老式for循环值得使用,因为它们是基础语言,除了您自己添加的内容之外,它们没有额外的开销:
case 'VOTE':
var updated = false;
for (var i = 0; i < state.length; i++) {
if (state[i].id === action.id) {
state[i].score += action.score; // or whatever
break;
}
for (var j = 0; j < state[i].users.length; j++) {
if (state[i].users[j].id === action.id) {
state[i].users[j].score += action.score; // or whatever
updated = true;
break;
}
}
if (updated) { break; }
}
案例“投票”:
var=false;
对于(变量i=0;i
请注意,我们在找到匹配项的那一刻就停止搜索,并且不需要将任何内容复制到新数组
搜索整个数组可能感觉像是一项繁重的操作,但请不要搞错,
.map
也在幕后进行搜索。从问题数组中获取问题:
const question = state.find(question => (question.id === action.id));
// do something with question
然后找到该用户并更新其分数:
const user = question && question.users.find(user => (user.id === action.id));
// do something with user
最快的是id查找,因此即使对于许多id,按id查找项的时间也几乎相同:
{
'123fdx12c1' : {
author: 'Anon',
score: 1,
users: [ '321fdx12c1', 'asd123f1fd1' ]
},
'321fdx12c1' : {
name: 'anon',
score: 1
},
'asd123f1fd1' : {
name: 'anon',
score: 1
}
}
作为旁注,一般情况下,解释语言中的函数调用比本机代码慢。在某些浏览器中,
.map
的速度可能比for-loop慢10-100倍 当然有,您只需更改属性状态。users[id]。score='something other'
@adeneo它看起来像状态。users
是一个数组而不是一个对象。是的,使用适当的数据库而不是将状态保存在内存中。数据库查询优化为快速。我认为action.id
可以匹配父对象的id或父对象之一的users
数组中的用户的id。@arbuthnott上述语句将从数组中搜索用户。对于父级问题
可以有另一个查找
来获取问题。@arbuthnott correct,id对应于父级(线程)或某个用户(注释)@Fawaz,如果我正确阅读了问题,您可能必须找到匹配的用户子对象,而不知道它所属的超级对象的id。@arbuthnott我同意。在这种情况下,它必须循环处理每个问题。虽然这是一个奇怪的数据结构。这似乎是迄今为止最好的答案,而且比我的答案快得多。我认为JS有一些内置的工具来实现这一点。此外,在搜索实际ID之前,我可以先获得超级对象的ID(为了对评论进行投票,必须打开超级对象/线程)。这应该会加快速度:这对于React+Redux是一种糟糕的方法。您将直接改变现有状态值,这将导致连接的组件无法重新渲染。需要不可变的更新,因为它们会产生新的引用,connect
依赖引用相等性检查来检测更改并导致重新呈现。有关更多详细信息,请参阅Redux文档中的和部分。因此,您的意思是:我应该先复制原始数组,然后直接修改其值,我想更改并将其作为新的原始数组返回,这样Redux引擎将比较我的当前状态和它提供的新状态,看看它们是否不同?@markerikson根据第二篇文章(常见错误2),我错了。这是否意味着我提供的原始解决方案是正确的?如果是这样的话,是否有更好/更快的方法同时兼容Redux?是的,问题中列出的原始方法看起来不错。如果知道该项的索引,还可以执行以下操作:constnewarray=oldArray.slice();newArray[index]={…newArray[index],{newValue:42}
。这意味着我们可以像这样改变对象:state.actionID.score=action.score。很好,我肯定会将其用于更大的项目,或者如果我使用实际的数据库而不是本地存储。