2017-09-17 6 views
1

私は自分のアプリケーションでRedditのような投票システムを作成しています。各オブジェクト(スレッド)はスコアプロパティと、親オブジェクトに似たオブジェクトの配列(スレッドのコメントと考える)を持っています。ここ
は簡単な例です:大きなオブジェクト配列内で単一のオブジェクトプロパティを突然変異させる最速の方法は何ですか?

{ 
    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; 
    }); 

それはちょうど、オブジェクトのプロパティを1つ変更するには、配列全体をマッピングします。これにはより速いアプローチがありますか?

+0

もちろん、 'state.users [id] .score = 'something else''プロパティを変更するだけです。 – adeneo

+0

@adeneo' state.users'は配列ではないオブジェクトです。 –

+0

ええ、メモリに状態を保持するのではなく、適切なデータベースを使用してください。データベースクエリは高速に最適化されています。 –

答えて

1

最速は、ID検索です

{ 
    '123fdx12c1' : { 
     author: 'Anon', 
     score: 1, 
     users: [ '321fdx12c1', 'asd123f1fd1' ] 
    }, 
    '321fdx12c1' : { 
     name: 'anon', 
     score: 1 
    }, 
    'asd123f1fd1' : { 
     name: 'anon', 
     score: 1 
    } 
} 

補足として、一般的な関数cインタプリタ言語のすべてがネイティブコードより遅いです。
一部のブラウザでは、.mapはforループより約10-100倍遅くなることがあります。

+0

これは、オブジェクトをmutateできることを意味します:state.actionID.score = action.score。ちゃんと、私はもっと大きなプロジェクトに使うか、ローカルストレージの代わりに実際のデータベースを使っているのかは間違いありません。 – jwm0

0

私は.map.filterがさまざまな(ほとんど良い)理由のために普及していることを知っています。

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; } 
    } 

我々は我々が試合を見つけた瞬間の検索を停止するために取得のお知らせ、そして何も:彼らは基本言語であり、彼らはあなたが自分で追加するもの以外に余分なオーバーヘッドを持っていないので、しかし、forループ昔ながら時には昔は使って価値があります新しい配列にコピーする必要があります。

アレイ全体を検索すると、重い操作のように感じるかもしれませんが、間違いなく、.mapもフードの下でそれをやっています。

+0

これはこれまでのところ私のものよりはるかに速い最高の答えと思われます。私は、JSにはそうするための組み込みツールがいくつかあると思っていました。また、実際のIDを検索する前に、スーパーオブジェクトのIDを最初に取得することもできます(コメントに投票するには、スーパーオブジェクト/スレッドを開く必要があります)。 https://gist.github.com/anonymous/758012809302ea02058cc15033585553 – jwm0

+0

これはReact + Reduxの悪いアプローチです。 **既存の状態値**を直接変更すると、接続されたコンポーネントが再レンダリングされません。変更が検出され、再レンダリングが発生するように、参照が等価であるかどうかに依存します。 [FAQ:再レンダリングしないコンポーネント](http:// redux。 js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html)のセクションを参照してください。 – markerikson

+0

あなたが言っていることは、元の配列のコピーを作成してから直接値を変更する必要があります。変更して新しいオリジナルとして返すので、Reduxエンジンは現在の状態を新しい状態と比較しますそれらが異なるかどうかを確認します。 – jwm0

0

が質問配列から質問を取得します。

const question = state.find(question => (question.id === action.id)); 
// do something with question 

そのユーザーを見つけると、そのスコアを更新:idでアイテムを見つけることがほぼ同じになるように

const user = question && question.users.find(user => (user.id === action.id)); 
// do something with user 
+0

'action.id'は、親オブジェクトのどちらかのidと一致していると思います。 – arbuthnott

+0

@arbuthnott上記のステートメントは、配列からユーザーを検索します。親の 'question'には、もう一つの' find'があります。 – Fawaz

+0

@arbuthnottが正しい、idは親(スレッド)またはユーザーの1人(コメント)に対応します – jwm0

関連する問題