Randomly Ordering a List in JavaScript

Here’s my problem: Using JavaScript, I want to randomly order a list of numbers from 1 to 10 for a small project I am working on…but how? Before I begin to talk about how I solved this, there are of course many options, and I am sure, some are better, but you just can’t beat discovering some things for yourself :-) So, keep that in mind as you peruse my master-solution!

Option 1 - Brute Force

One possibility is to keep guessing numbers (within the allowed range of 1-10) until I find one I haven’t used and then add it to a list, until I have 10 numbers. That would work but you can imagine that there would be duplicates and that constant (pain) checking for whether a number has been already used.

Numbers Found: None
Guess 1: 7
Yay! It hasn't been used.

Numbers Found: 7
Guess 2: 4
Yay! It hasn't been used.

Numbers Found: 7, 4
Guess: 4
Rats! Guess again; I have that one.
Guess 6:
Yay! It hasn't been used.

{yawn}

Option 2 - Don’t Even Try

Uh? Well, what if I just had a fairly large number of possibilities already computed and just randomly chose between them?

1...\[3, 4, 1, 7, 6, 5, 10, 2, 9, 8\]
2...\[2, 9, 8, 3, 4, 1, 7, 6, 5, 10\]
3...\[10, 3, 7, 4, 2, 9, 6, 8, 5, 1\]

{cheat}

Again, that would work, but it does seem a teensy bit wasteful of memory and smacks of…well…lack of randomness.

Option 3 - Using Random Numbers

Aren’t we trying to already randomise our list? What do I mean? Well, what if we could have a list of numbers already produced (1-10)? That would avoid the duplication problem that I have with Option 1. Then, together with those, I generate a series of random numbers on a 1-1 basis so that each of my ten values has it’s own random value; any value will do, I won’t be picky. Next, I sort the list based on the random number (not the original 1-10) before plucking out my original number in it’s new position. That avoids my main issue with option 2. Let’s see a part of that in action:

Step 1 - Generate Random Numbers

#...random value
1...0.832
2...0.279
3...0.941
4...0.346
{ignored 5-9 for brevity}
10...0.981

Step 2 - Sort Them

#...random value
2...0.279
4...0.346
1...0.832
3...0.941
{ignored 5-9 for brevity}
10...0.981

Step 3 - Pluck Them!

OK :-) I don’t need to show this step. That would seem to work and won’t be too onerous on memory or processing. It’s time to bring out the JavaScript guns and explain how we might implement this.

Creating the Original List of Numbers

To do this, I am going to use JavaScript objects because that way, I can store two pieces of information: the number (1-10) and its associated random value. Oh, and I will need 10 of them, so might as well use an array. Let’s see how that looks, so far:

1
2
3
4
var table = [10];
for (var index = 0; index < size; index++) {
table[index] = { table: index + 1 }
}

This gives me an array of (anonymous) objects which contain one property: the number, that is referenced by the attribute table. Adding in the random component requires one small change:

1
2
3
4
var table = [10];
for (var index = 0; index < size; index++) {
table[index] = { table: index + 1, order: Math.Random() }
}

To access the properties, all we need to do is something like:

1
table[0].table

…to access the number at position 1 or:

1
table[0].order

…to access the random number associated with it, using the label order. But what about the sorting? This isn’t sorted (randomized), is it?

Sorting the Numbers (aka Randomizing Them)

It is possible to sort arrays but to do that (in this custom way) I need to provide a function which will act on each individual element of the array. Since we are using anonymous objects, JavaScript has no way of understanding what to do with them, so we tell it.

1
2
3
4
5
6
7
8
9
function CompareTables(v1, v2) {
if (v1.order < v2.order) {
return -1;
} else if (v1.order > v2.order) {
return 1;
} else {
return 0;
}
}

Here, for each element in the array, we need to compare it against another element. I say we, but actually, as you will see, JavaScript will do the heavy lifting for us. Let’s assume, though, we just have two elements - we just need to show how we compare them and in this example, they will end up in the variables v1 and v2. Next, for each pair, we look to see if one is small than the other. If it is, we return -1. If it is in fact bigger, we return 1 and for anything the same, the result is 0. Using those values, JavaScript is able to work out where to place everything. You can see why this needed to be implemented because we are in fact accessing the order element of each value, as you can see above, and not some scalar value.

Putting it all Together

To make this more digestible, I have missed a couple of points out so it’s important to stitch this together to see how it works as a whole. In the code below, you can see how I have wrapped the array creation up into a more flexible solution, allowing the user to specify how many values to create. Also, you can see where I call the sort function on the array, linking the two parts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function BuildTable(size) {
var table = \[size\];
for (var index = 0; index < size; index++) {
table\[index\] = { table: index + 1, order: Math.random() }
}
table.sort(CompareTables);
return(table);
}

function CompareTables(v1, v2) {
if (v1.order < v2.order) {
return -1;
} else if (v1.order > v2.order) {
return 1;
} else {
return 0;
}
}

But I Don’t Want To Randomize Numbers!

That’s OK. Just change where I set the table: index+1 to be what you would prefer. And there you have it, or as Popeye would say:

“I am what I am, and that’s all that I am.”


Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com