Consider the following mark up:
<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>
I want to generate a random order that both of these lists would use. So a desired output could look like:
<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
will always have the same number of children in it as #elements2
and visa versa.
My pseudo code looks like like:
// 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
Does my strategy seem like it would be efficient for the task at hand? (I will produce working code in a minute.) If not, what would be a better way to go about this? Thanks for your help!
Edit: Here is a fiddle to mess around with.
A simple way would be to use a documentFragment for this:
// 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);
You can sort the the second array of selected elements using an array of values that has sorted the first collection.
// 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);
To simply randomise the order of an Array , you could do something like this
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
}
}
You'll need to convert your HTMLCollection to something non-live so you can use it more easily, for example use
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);
Now for the thing you actually want to randomise (if you don't want to modify the function above to shuffle two arrays at the same time, see below)
i = nodes1.length, a = new Array(i);
while (i--) a[i] = i;
// a = [0, 1, 2, 3, ...]
Now simply randomise a
, and re-append the nodes following the new order of numbers
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]]);
}
Demo . I've ignored var
but remember to use it as applicable.
Decided to add a modified version of the shuffle for 2 Arrays , as this will most likely be much faster.
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
}
}
Here you would just do
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]);
}
Demo .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.