Because you asked for elegant, I like to implement a more functional style of programming here. The code below does what you want. You supple the shuffle
function with your array, the max number of times you want it shuffled (the higher the number, the better the shuffle is), and true
to keep the first element in place, false
to keep the last.
function shuffle(array, maxTimes, first) {
var temp = (first) ? array.reverse().pop() : array.pop();
Array.from(
Array(Math.round(Math.random()*maxTimes))
.keys()).forEach(val => array = array.reduce((acc,val) =>
(Math.random() > 0.5) ? acc.concat([val]) : [val].concat(acc),[]));
return (first) ? [temp].concat(array.reverse()) : array.concat([temp]);
}
Example usage:
shuffle(['A','B','C','D','E'], 10, true);
Output: ["A", "C", "D", "B", "E"]
I hope this is what you're looking for and answers your question.
Edit
Turns out you can get the shuffle logic all in one line (when removing the unnecessary newlines). When you add the two lines to retain the first or last character, you can essentially create this function with three lines of code.