I think it would. With real cards we shuffle the deck and then pick some cards from the top of the top of the deck. This is what you'll probably be doing with the shuffle function, thereby modelling the real world use.
With Math.Random(), you're randomly picking a card from an un-shuffled deck. The key here is randomness (which is not really random btw). So, although this isn't modelled after the real world use, the end result is the same.
I would suggest Math.Random() because it will, although not significantly, be faster than using _.shuffle's (Fisher–Yates) algorithm.
javascript - Shuffle multiple arrays in the same way but with Lodash - Stack Overflow
How to randomize (shuffle) a JavaScript array? - Stack Overflow
How to shuffle an array of objects in javascript? - Stack Overflow
How To Shuffle Arrays
» npm install lodash.shuffle
The de-facto unbiased shuffle algorithm is the Fisher–Yates (aka Knuth) Shuffle.
You can see a great visualization here.
function shuffle(array) {
let currentIndex = array.length;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
let randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
}
// Used like so
let arr = [2, 11, 37, 42];
shuffle(arr);
console.log(arr);
Here's a JavaScript implementation of the Durstenfeld shuffle, an optimized version of Fisher-Yates:
/* Randomize array in-place using Durstenfeld shuffle algorithm */
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
It picks a random element for each original array element, and excludes it from the next draw, like picking randomly from a deck of cards.
This clever exclusion swaps the picked element with the current one, then picks the next random element from the remainder, looping backwards for optimal efficiency, ensuring the random pick is simplified (it can always start at 0).
Note the loop condition skips i==0, since j can only ever be 0 then, leading to no swap.
Algorithm runtime is O(n). Note that the shuffle is done in-place so if you don't want to modify the original array, first make a copy of it with .slice(0).
EDIT: Updating to ES6 / ECMAScript 2015
The new ES6 allows us to assign two variables at once. This is especially handy when we want to swap the values of two variables, as we can do it in one line of code. Here is a shorter form of the same function, using this feature.
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
Try sorting like this snippet:
console.log( [
{ some: 1 },
{ some: 2 },
{ some: 3 },
{ some: 4 },
{ some: 5 },
{ some: 6 },
{ some: 7 },
]
.sort( () => Math.random() - 0.5) );
In reponse to Martin Omanders comment: here's a shuffle method according to the Fisher-Yates algorithm
const result = document.querySelector("pre");
for (let i=0; i<20; i+=1) {
result.textContent +=
JSON.stringify(shuffleFisherYates([0,1,2,3,4,5,6,7,8,9])) + '\n';
}
function shuffleFisherYates(array) {
let i = array.length;
while (i--) {
const ri = Math.floor(Math.random() * i);
[array[i], array[ri]] = [array[ri], array[i]];
}
return array;
}
<pre></pre>
Which may be condensed to a one liner (note: this one liner will not compile in the Google Closure Compiler with level advanced):
const shuffle = array =>
[...Array(array.length)]
.map((el, i) => Math.floor(Math.random() * i))
.reduce( (a, rv, i) => ([a[i], a[rv]] = [a[rv], a[i]]) && a, array);
const result = document.querySelector("pre");
for (let i=0; i<100; i+=1)
result.textContent +=
JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])) + '\n';
<pre></pre>
Here is one more example based on lodash _.shuffle.
const array = [
{ some: 1 },
{ some: 2 },
{ some: 3 },
{ some: 4 },
{ some: 5 },
{ some: 6 },
{ some: 7 },
];
console.log(_.shuffle(array));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>