Possibly easier; but not otherwise better.
To answer myself, with some extra help from about.com
(
http://javascript.about.com/library/blsort2.htm) the following solution
appears to work just fine:
function randOrd(){
return (Math.round(Math.random())-0.5);
}
var a = new Array('fourth','fifth','sixth','etc')
a.sort(randOrd)
a.unshift('first','second','third')
That method was discussed here some years ago, as an example of amusing
but ludicrous programming.
The specification of Array.sort calls for repeatable comparisons; the
sort algorithm to be used is not defined, and may vary from browser to
browser, version to version. With non-repeatable comparison, the result
cannot be guaranteed : the sort algorithm might not even finish in some
systems.
An efficient shuffle of N elements takes time O(N), and uses O(N) calls
of Random. The sort algorithm will take time at least about O(NlogN)
calling Random O(2NlogN) times.
The first question you should consider is whether you actually need a
Shuffle. A Shuffle starts with all the elements present on some order
and ends with them all on an independent order, probably in the same
Array. You might be able to install the first three elements in direct
order, then the rest in random order.
For shuffle-in-place, it would be easier to keep the last three elements
unmoved, by doing a standard shuffle but lying about the length. So,
consider
function Random(X) {
return Math.floor(X*(Math.random()%1)) /* %1 : Opera */ }
function ShuffleX(Q, x) { var R, T, J
for (J=Q.length-1 -x ; J>0 ; J--)
{ R=Random(J+1) ; T=Q[J] ; Q[J]=Q[R] ; Q[R]=T }
return Q }
A = [1,2,3,4,5,6,7,8,9]
A = A.reverse()
ShuffleX(A, 3)
A = A.reverse()
In that, ShuffleX is the FAQ-cited standard (Knuth?) algorithm, modified
by the addition of the parameter x.
Now you can optimise by rewriting ShuffleX so that it works the other
way round, and omit the reversals.
It's a good idea to read the newsgroup c.l.j and its FAQ. See below.