2017-05-02 19 views
1

私は次のようなオブジェクトの配列を持っています:​​複数の配列要素をインデックス間で効率的にランダム化する方法はありますか?

各エントリはその配列内のオブジェクトです。私がする必要があるのは、見出しではない各要素の順序をランダム化することです。各見出しは最初のインデックスにとどまらなければならないが、2つの見出しの間の要素はランダム化されなければならない。付属の写真には、どのように見えるべきかの描写があります。

見出しと定期的な要素間の唯一の違いは、その値がこの#のH番号のように見える正規表現であるということである[0-9] +

だから、私がやったことだった: 私はを反復処理します各見出しのインデックスに注目してください。

次に、インデックス配列を繰り返し、複数のより小さな配列(各見出しに対して1つのグループ)に分割します。

次に、分割配列を含む配列を繰り返し、各配列をインデックス0からスプライスし(見出し要素を削除)、これらの値をシャッフルし、配列をシフトして先頭にヘッドライン要素を追加します。

最後に、splittedArrayOfArraysのすべての配列を必要な配列に連結します。これはcurrent.choicesです。

3回の繰り返しを実行するのはパフォーマンス上非常に賢明ではないようですが、配列から要素のグループのみをランダム化する方法はありますか?ここで

が、私はそれを動作させるために一緒にハッキングコードです:

    var headlineIndexes = []; 
        var splittedArrayOfArrays = []; 
        for (var ii = 0; ii < current.choices.length; ii++) { 
         if (regex.test(current.choices[ii].value)) { 
          headlineIndexes.push(ii); 
         } 
        } 
        for (var ii = 0; ii < headlineIndexes.length; ii++) { 
         //if there is another headlineIndex, split Array until that index 
         if (headlineIndexes[ii + 1]) { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii], headlineIndexes[ii + 1]) 
         } 
         //if not, split until end of array 
         else { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii]); 
         } 
        } 
        current.choices = []; 
        for (var ii = 0; ii < splittedArrayOfArrays.length; ii++) { 
         //remove first element and store in firstElem 
         var firstElem = splittedArrayOfArrays[ii].splice(0, 1); 
         //call shuffle with remaining elements, which shuffles the elements WITHOUT the headline 
         shuffle(splittedArrayOfArrays[ii]); 
         // re-add the headline as first elem of splittedArray 
         splittedArrayOfArrays[ii].unshift(firstElem[0]); 
        } 
        current.choices = splittedArrayOfArrays.reduce(function(prev, next) { 
         return prev.concat(next) ; 
        }); 

編集:私はsplittedArrayOfArraysを反復する理由はありませんでした実現し、すべてがforループを二から行われている可能性があります。私はこれが配列の中に持っている最大40桁の要素のために十分効率的だと思います。ここでは、最終的なコードです:3回の反復を実行

var headlineIndexes = []; 
        var splittedArrayOfArrays = []; 
        //save indexes at which we have headlines 
        for (var ii = 0; ii < current.choices.length; ii++) { 
         if (regex.test(current.choices[ii].value)) { 
          headlineIndexes.push(ii); 
         } 
        } 
        //split choices array into groups for each headline. 
        for (var ii = 0; ii < headlineIndexes.length; ii++) { 
         //if we have another headline, make new array with elements from current index to next index 
         if (headlineIndexes[ii + 1]) { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii], headlineIndexes[ii + 1]) 
         } 
         //else, new array from current index to end of choices array 
         else { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii]); 
         } 

         //remove first element which is the headline, store in firstElem 
         var firstElem = splittedArrayOfArrays[ii].splice(0, 1); 
         //shuffle the choices of the group 
         shuffle(splittedArrayOfArrays[ii]); 
         //add the first element back to the first position of the group 
         splittedArrayOfArrays[ii].unshift(firstElem[0]); 
        } 

        //delete choices array 
        current.choices = []; 
        //concatenate group arrays into the choices array 
        current.choices = splittedArrayOfArrays.reduce(function(prev, next) { 
         return prev.concat(next) ; 
        }); 

答えて

0

私はsplittedArrayOfArraysを反復する理由がないことに気付きました。すべてが2番目のforループから実行されている可能性があります。私はこれが配列の中に持っている最大40桁の要素のために十分効率的だと思います。最終コードは

    var headlineIndexes = []; 
        var splittedArrayOfArrays = []; 
        //save indexes at which we have headlines 
        for (var ii = 0; ii < current.choices.length; ii++) { 
         if (regex.test(current.choices[ii].value)) { 
          headlineIndexes.push(ii); 
         } 
        } 
        //split choices array into groups for each headline. 
        for (var ii = 0; ii < headlineIndexes.length; ii++) { 
         //if we have another headline, make new array with elements from current index to next index 
         if (headlineIndexes[ii + 1]) { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii], headlineIndexes[ii + 1]) 
         } 
         //else, new array from current index to end of choices array 
         else { 
          splittedArrayOfArrays[ii] = current.choices.slice(headlineIndexes[ii]); 
         } 

         //remove first element which is the headline, store in firstElem 
         var firstElem = splittedArrayOfArrays[ii].splice(0, 1); 
         //shuffle the choices of the group 
         shuffle(splittedArrayOfArrays[ii]); 
         //add the first element back to the first position of the group 
         splittedArrayOfArrays[ii].unshift(firstElem[0]); 
        } 

        //delete choices array 
        current.choices = []; 
        //concatenate group arrays into the choices array 
        current.choices = splittedArrayOfArrays.reduce(function(prev, next) { 
         return prev.concat(next) ; 
        }); 
1

は、私はそれについて心配しないでしょう

[...]パフォーマンスに非常に賢明なようではありません。グループに数千の見出しがあり、数十万の要素がシャッフルされない限り、このルーチンはパフォーマンスに全く影響しません。

本当に調整したい場合は、元の配列の内側にある意味でシャッフルして、配列をコピーして再度組み込む必要がありません。

+0

ですが、元の配列をシャッフルしても配列内のグループは失われます。私はヘッドラインのインデックスを変更する必要はありませんし、グループ内の要素をシャッフルするだけです(したがって、配列を分割し、シャッフルして、それらをまとめる)。 –

+0

配列の特定の範囲内で、2つの見出しの間にシャッフルするだけです。あなたはもちろん、事前にヘッドラインの位置を決定しなければならなかった。次に、インデックス0から最後まで配列をシャッフルする代わりに、見出しの直後のインデックスから次の見出しの前に、すべての範囲をシャッフルするまでインデックスから開始します。 – pfirpfel

関連する問題