title: How to efficiently randomize multiple array elements between indexes?
body: <p>I have an array of objects that looks like this: <a href="https://i.stack.imgur.com/jaVcy.png" rel="nofollow noreferrer">https://i.stack.imgur.com/jaVcy.png</a></p>
  
  <p>Each entry is an object within that array. What I need to do is randomize the order of each element that is NOT a headline. Each headline must remain at the initial index, but the elements between two headlines must be randomized. In the attached picture is a depiction of how it should look like.</p>
  
  <p>The only difference between a headline and a regular element is that its value is a regex that looks like this #H#[0-9]+</p>
  
  <p>So, what I did was:
  I iterate through the array, noting the indexes of each headline. </p>
  
  <p>Then, iterate through the indexes array and split the array into multiple, smaller arrays (one group for every headline).</p>
  
  <p>Then, iterate yet AGAIN through the array that contains the split arrays, splice each array starting at index 0 (remove the headline element), shuffle these values, unshift the array and add the headline element at the beginning.</p>
  
  <p>Finally, concatenate all the arrays in splittedArrayOfArrays into the array that I need, which is current.choices.</p>
  
  <p>Performing three iterations doesn't seem very wise in performance, is there any other possible way of randomizing only groups of elements from an array?</p>
  
  <p>Here's the code I hacked together to make it work:</p>
  
  <pre><code>                    var headlineIndexes = [];
                      var splittedArrayOfArrays = [];
                      for (var ii = 0; ii &lt; current.choices.length; ii++) {
                          if (regex.test(current.choices[ii].value)) {
                              headlineIndexes.push(ii);
                          }
                      }
                      for (var ii = 0; ii &lt; 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 &lt; 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) ;
                      });
  </code></pre>
  
  <p>EDIT: I realized there was no reason to iterate over the splittedArrayOfArrays, everything could have been done from the second for loop. I think this is efficient enough for a maximum of 40ish elements that I'd have in the array anyway. Here's the final code:</p>
  
  <pre><code>var headlineIndexes = [];
                      var splittedArrayOfArrays = [];
                      //save indexes at which we have headlines
                      for (var ii = 0; ii &lt; 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 &lt; 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) ;
                      });
  </code></pre>