如何在索引之间有效地随机化多个数组元素?

时间:2017-05-02 11:56:44

标签: javascript arrays random concat

我有一个如下所示的对象数组:https://i.stack.imgur.com/jaVcy.png

每个条目都是该数组中的一个对象。我需要做的是随机化每个不是标题的元素的顺序。每个标题必须保留在初始索引处,但两个标题之间的元素必须随机化。附图中描述了它应该是什么样子。

标题和常规元素之间的唯一区别是它的值是一个看起来像这样的正则表达式#H#[0-9] +

所以,我做的是: 我遍历数组,注意每个标题的索引。

然后,遍历索引数组并将数组拆分为多个较小的数组(每个标题一个组)。

然后,通过包含拆分数组的数组迭代AGAIN,从索引0开始拼接每个数组(删除标题元素),随机移动这些值,取消移动数组并在开头添加标题元素。

最后,将splittedArrayOfArrays中的所有数组连接到我需要的数组中,即current.choices。

执行三次迭代在性能上似乎不是很明智,是否有其他任何可能的方法只从数组中随机化元素组?

这是我为了让它发挥作用而共同破解的代码:

                    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个元素是足够有效的。这是最终的代码:

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

2 个答案:

答案 0 :(得分:1)

  

执行三次迭代在性能[...]

中似乎不太明智

我不担心。除非有成千上万的头条新闻和成千上万的元素进行混洗,否则这个例程根本不会影响性能。

如果你真的想要调整它,你就可以在原始阵列中进行混乱,这意味着不必复制数组并将它们重新组合在一起。

答案 1 :(得分:0)

我意识到没有理由迭代splittedArrayOfArrays,一切都可以从第二个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) ;
                    });