我如何在jquery/javascript中随机化两组元素的顺序,使它们与每个顺序保持同步

How can I randomize the order of two sets of elements in jquery/javascript, so that they remain in sync with each order?

本文关键字:顺序 同步 元素 两组 jquery javascript 随机化      更新时间:2023-09-26

考虑以下标记:

<div id="elements1">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
</div>
<br/>
<ul id="elements2">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

我想生成一个这两个列表都会使用的随机顺序。因此,期望的输出可能看起来像:

<div id="elements1">
    <div>Item 2</div>
    <div>Item 5</div>
    <div>Item 3</div>
    <div>Item 1</div>
    <div>Item 4</div>
</div>
<br/>
<ul id="elements2">
    <li>Item 2</li>
    <li>Item 5</li>
    <li>Item 3</li>
    <li>Item 1</li>
    <li>Item 4</li>
</ul>

#elements1将始终具有与#elements2相同数量的子节点,反之亦然。

我的伪代码看起来像这样:

// see how many child elements in #elements1
// create order array based on # of child elements in i.e. [1,2,3,4,5]
// randomize array
// use order array to reorder both #elements1 and #elements2
// .appendTo() respective parents

我的策略看起来对手头的任务有效吗?(我将在一分钟内生成工作代码。)如果不是,有什么更好的方法来做这件事呢?谢谢你的帮助!

编辑:这是一个可以摆弄的提琴

一个简单的方法是使用一个documentFragment:

// lists with equal length
var list1 = document.getElementById('elements1');
var list2 = document.getElementById('elements2');
// a place to stash the items while randomizing
var stash1 = document.createDocumentFragment();
var stash2 = document.createDocumentFragment();
// initial length
var length = list1.childNodes.length;
// choose the same random child from the lists
// put them in their stashes preserving the new order
while(length > 0){
    var random = Math.floor((Math.random()*--length));
    stash1.appendChild(list1.childNodes[random]);
    stash2.appendChild(list2.childNodes[random]);
}
// put the elements back in the lists when done
list1.appendChild(stash1);
list2.appendChild(stash2);

演示:http://jsfiddle.net/louisbros/NPPpt/

要简单地随机化数组的顺序,您可以这样做

function shuffleArray(a) { // Fisher-Yates shuffle
    var i = a.length, t, j;
    while (--i) { // loop over each item in array (except 0 because no point)
        j = (Math.random() * (i+1)) | 0; // random Int j <= i
        t = a[i], a[i] = a[j], a[j] = t; // swap items i and j
    }
}
你需要将你的HTMLCollection转换为非活动的东西,这样你可以更容易地使用它,例如使用
elements1 = document.getElementById('elements1'); // cache for later
nodes1 = Array.prototype.slice.call(elements1.children); // children to Array
elements2 = document.getElementById('elements2');
nodes2 = Array.prototype.slice.call(elements2.children);

现在对于你真正想要随机化的东西(如果你不想修改上面的函数来同时随机化两个数组,见下文)

i = nodes1.length, a = new Array(i);
while (i--) a[i] = i;
// a = [0, 1, 2, 3, ...]

现在简单地随机化a,并按照新的数字顺序重新添加节点

shuffleArray(a); // a = e.g. [4, 8, 2, 5, ...]
for (i = 0; i < nodes1.length; ++i) {
    elements1.appendChild(nodes1[a[i]]); // append in new order
    elements2.appendChild(nodes2[a[i]]);
}

。我忽略了var,但请记住在适用时使用它。


决定为2 数组添加一个修改版本的shuffle ,因为这可能会快得多。

function shuffleTwoArrays(a, b) { // Shuffle 2 arrays same length in same way
    var i = a.length, t, j;
    while (--i) { // loop over each item in array (except 0 because no point)
        j = (Math.random() * (i+1)) | 0; // random Int j <= i
        t = a[i], a[i] = a[j], a[j] = t; // swap items i and j in a
        t = b[i], b[i] = b[j], b[j] = t; // swap items i and j in b
    }
}

这里你只需要做

shuffleTwoArrays(nodes1, nodes2); // shuffle both the same
for (i = 0; i < nodes1.length; ++i) {
    elements1.appendChild(nodes1[i]); // re-append to achieve new order
    elements2.appendChild(nodes2[i]);
}

您可以使用已对第一个集合进行排序的值数组对第二个选定元素数组进行排序。

// selecting elements
var $elem1 = $('#elements1 div'),
    $elem2 = $('#elements2 li');
// cloning elements (for reordering)
var $ordered1 = $elem1.clone(),
    $ordered2 = $elem2.clone();
// randomizing elements
var helper = [],
    i = -1,
    $randomized1 = $elem1.sort(function () {
        var n = 0.5 - Math.random();
        helper.push(n);
        return n;
    }),
    $randomized2 = $elem2.sort(function () {
        return helper[++i];
    });
// .appendTo() respective parents
$('#elements1').append($randomized1);
$('#elements2').append($randomized2);
http://jsfiddle.net/zGLZG/