This is a set of functions which may be used in order, for instance, to shuffle digital cards, but can also have a role in much less trivial circumstances; they all deal with
shuffling arrays issues.
The basic procedure to shuffle an array is obvious, namely:
- Extracts a random entry from the input array.
- Assigns it to the output array.
- Make sure the just extracted entry can't be extracted again.
That's all which is needed.
You can find faster approaches, such as:
var array = [0,1,2,3,4];
function comp(a,b){
return (Math.random() < 0.5) ? -1 : 1;
}
alert(array.sort(comp));
An Orazio Gentileschi painting, Annunciation, 1623
|
That approach is undoubtedly faster for it relies on the fact you can use a
sort built in function as a
proxy not to
sort but to shuffle.
The increase in speed derives from the fact it doesn't loop to splice the input array, but relies on the built in method
sort, which in its own turn relies on a
quicksort implementation.
Yet, let me say: though both approaches are functional, you will find persons who dubbed my sorting approach as "ridiculous" (it is an inveterate habit of programmers that they can't resist making
gratuitous and unwarranted
rebuttals).
Do
not get discouraged: the sorting approach above is faster, yet the logics in my function below are the
second best after that:
extract, assign, delete - that is positively what is needed and not one comma more.
Why then a second best (and if it would be a
tenth best it would still go on being
respectable, not
ridiculous) has to be called "ridiculous" can
only be ascribed to
sheer gratuity.
Of course, needless to say that the critic professor
never worked out that this approach was deviced to perform a
symmetrical shuffle too: for which you just can
not use
without limitations the shorter method above: in fact by using
sort you can still implement a parallel (=symmetrical) shuffling namely shuffle
multiple arrays keeping the same entry-to-entry symmetry they had before being shuffled, and
yet with a limitation: the arrays to be all shuffled in parallel must also be
all of the same length - a limitation that a parallel shuffling with
my function
bypasses.
Anyway additionally, rather than criticizing by mocking, I will present you also with a parallel shuffling function that uses
sort, but that has the above mentioned limitation: yet as far as I know you won't find online to date (2004) a parallel sorting that
illustrates and performs a
symmetrical (parallel) shuffling by using
sort.
I have learned over time that you'd
never dismiss the others if you're not sure what they're after, or what they could create with a minimum of input
respectfully lent: some guys write longer codes because they are unable to focus on the simpler thing alone: I want the challenge, not the obvious. And my codes are never meant to do one thing alone.
Never.
You can use this function of mine for shuffling one array if you want: I assure you it is
dignified, also becasue it is very difficult to be off the ball when all you do to shuffle is:
1: random extract, 2: assign to output, 3: delete old record
which is
exactly what a
shuffling as a conceptual paradigm is all about, and you achieve those
3 steps in a
runtime code of exactly 3 lines.
- Maybe you'd like to use this function in association with the one which deals a defined and limited amount of entries out of a bigger array, namely extracting from it a subset of dishomogeneous entries: in other words you could shuffle (cards?) with this function, and deal (cards?) with this other function - click.
- When you run a random number generating function, actually it is not random: it secretively gets an argument: the time expressed in milliseconds as it appears on the machine where the script is running, and uses it as a seed to generate a "random" number given that input (elaborates on it, that is).
Because each millisecond is different from the next one, you can get random numbers that are or appear random: none the less differentiating between milliseconds is a very fast lane, and thus you have a very remote chance you may get two subsequent numbers with a statistical occurrence higher than usual: it is not likely to happen, but you may want to consider that you can still shuffle its output... twice or more, exactly like humans do with actual cards indeed.
It is not necessary, but it is an option I lend to you.
- If you want to shuffle recursively the output twice or more, pass to the function a second argument named recur: it must be a number and if it is passed, the output will be recursively shuffled as many times as the recursive number dictates. If the recursive argument is set to 1, it recurs once at least: namely, it actually shuffles twice. Example:
shuffleArray(array, 4)
- The function produces a copy of the input array which is the only argument that is necessary to provide. Given a foo foo Array like for instance:
var testArray1=new Array(1,2,3,4,5,5,6,7,8,9,10,11,12,13,14,15);
A possible way to invoke our subroutine is thus:
shuffleArray(testArray1)
There can be a specific occurrence: you may want to shuffle an array, but you also have other arrays whose sequential order is, for some reason, to be kept symmetrical to the leading array: that is, if from a leading array1 you move, say, the element in position [3] to position [5] as a consequence of a
randomly shuffling process, you may need that also the corresponding entries in some array2 (and/or array3, array4 and so on) perform
that very same shift among those
corresponding very same indexes.
The
symmetricalSorting function accomplishes this.
You have pass to it arguments as follows:
- You pass to it the arrays already chained in the backbone of a bigger array (that is, a list all of your input arrays within one bigger array) which thus holds array1, array2 , array3 etc...:
var chain=new Array(array1, array2, array3) //etc...
var foo = symmetricalShuffle(chain);
- If you want to perform on these arrays a recursive shuffling, just add a secdond argument which must be a number (mandatory! defaults to zero) representing the amount of recursive shuffles (in the example below, number is which performs 6 shuffles - zero is considered the first shuffle). Example:
var foo = symmetricalShuffle(chain, );
The function returns
invariably a chain (matrix), namely an Array, whose each entry is an array itself, and all these entries are arrays that got shuffled accordingly to the same process; the output data structure is something like:
var foo= symmetricalShuffle(chain, 1)
foo[0]=Array
foo[1]=Array
foo[2]=Array
etc... therefore an entry may be
foo[2][numX].
Of course, for a symmetrical shuffling it is assumed that the length of the arrays that have to be shuffled symmetrically is the same. If it isn't, those arrays whose length falls short would be assigned "
undefined" values for each slot they fail to match. This is unavoidable, to preserve the original symmetry in case of input arrays of varying lengths. Anyway, this is a fair price to pay for in this way it does
not mess up the process in case lengths do not match.
In the test form below such
undefined entries (
typeof equals "
undefined") are not present by default, but if for instance you curtail one of the
input arrays of a few entries (or you add a few to one of them), you will see that in the arrays whose length is minor a few additional empty spaces are in place for the missing entries. That is the way an
undefined entry would appear in the
test form below: that is, you will see as a
result some sets of commas including a blank space and not a value.
Here is your codex:
Alternatively, I give to you here also the to date (2004) only online code that performs a parallel shuffling by using sort. There are a couple of
caveats though:
- The function accepts one argument only.
It must be an array.
Each of its entries must be an array on its own: namely each is one of the arrays you want to shuffle symmetrically.
- The length, namely the amount of elements present in each of the latter arrays, must be identical - that is, for instance all arrays must have a length of, say, 100: no one then can be of, say, 98 or say 101. One length for all, and no undefined entries please.
If you curtail one of the input arrays in the test form and then run this sortMultishuffle function, the shorter (only the shorter ones) arrays would exhibit no symmetry if not by mere chance!
- It returns the same argument, with the ranked arrays shuffled symmetrically. It affects the originals: shuffling by using sort does not yield copies.
The name of this quicksort oriented function is
sortMultishuffle, so:
sortMultishuffle( new Array(array1, array2, array3 /*etc...*/) );