Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/404.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 什么';在一个大的对象数组中改变单个对象属性的最快方法是什么?_Javascript_Reactjs_Optimization_Redux_React Redux - Fatal编程技术网

Javascript 什么';在一个大的对象数组中改变单个对象属性的最快方法是什么?

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'

我正在我的应用程序中创建一个类似Reddit的投票系统。每个对象(线程)都有一个score属性和一个类似于父对象的对象数组(将其视为线程的注释)。
以下是一个简化的示例:

{
  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。很好,我肯定会将其用于更大的项目,或者如果我使用实际的数据库而不是本地存储。