4

I'm trying to sort multiple arrays within an array (which also has to be shuffled). A simplified example is:

let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
...
];

const shuffled = shuffle(toShuffle);

// outout would look something like:
// [
//   [8, 6, 5, 7, 9],
//   [4, 3, 1, 5, 2],
//   [19, 26, 10, 67],
//   ...
// ]

This needs to be flexible, so any number of arrays with any amount of values should be valid.

Here is what I've tried:

function shuffle(a) {
  for (let e in a) {
    if (Array.isArray(a[e])) {
      a[e] = shuffle(a[e]);
    } else {
      a.splice(e, 1);
      a.splice(Math.floor(Math.random() * a.length), 0, a[e]);
    }
  }

  return a;
}

console.log("Shuffled: " + shuffle([
  [1, 2, 3, 4, 5],
  [5, 4, 3, 2, 1]
]))

But it's not working as intended. Is their an easier way to do this? Or is my code correct and just buggy.

7
  • You say it's not working as intended ... what's the intended result look like? Commented May 13, 2022 at 0:14
  • I don't understand what you're doing in the else block. You're removing the current element of the array, but you never put it back. Commented May 13, 2022 at 0:14
  • @Barmar I'm removing the e element from the array, then adding it back in a random position. Commented May 13, 2022 at 0:15
  • No you're not. When you splice out the e element, a[e] is now the element that used to be a[e+1]. So you're moving that to a random position. You never add back the original a[e]. Commented May 13, 2022 at 0:17
  • If you want to swap two array elements, do temp = a[e]; random = Math.floor(Math.random() * a.length); a[e] = a[random]; a[random] = temp; Commented May 13, 2022 at 0:19

2 Answers 2

2

You can use Array.from() to create a new shallow-copied array and then to shuffle Array.prototype.sort() combined with Math.random()

Code:

const toShuffle = [
  [1, 2, 3, 4, 5],
  [9, 8, 7, 6, 5],
  [10, 67, 19 ,27]
]

const shuffle = a => Array.from(a).sort(() => .5 - Math.random())
const result = toShuffle.map(shuffle)

console.log('Shuffled:', JSON.stringify(result))
console.log('To shuffle:', JSON.stringify(toShuffle))

Sign up to request clarification or add additional context in comments.

2 Comments

I really like this answer, it's more simple. Array.from() is awesome, just read the MDN page. Very useful.
Except it doesn't shuffle the toShuffle array itself...
2

You almost got it. The problem is that you are removing one item from an array, instead of capturing the removed item and them placing in a random position:

let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
];

function shuffle(a) {
  a = [...a]; //clone array
  for (let e in a) {
    if (Array.isArray(a[e])) {
      a[e] = shuffle(a[e]);
    } else {
      a.splice(~~(Math.random() * a.length), 0, a.splice(e, 1)[0]);
    }
  }

  return a;
}

console.log(JSON.stringify(shuffle(toShuffle)))
console.log(JSON.stringify(toShuffle))

[EDIT] The original code did not shuffle the parent array, if you need shuffle everything recursively, you can use this:

let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
];

function shuffle(a) {
  a = a.map(i => Array.isArray(i) ? shuffle(i) : i); //clone array
  a.sort(i => ~~(Math.random() * 2) - 1); //shuffle
  return a;
}

console.log("shuffled", JSON.stringify(shuffle(toShuffle)))
console.log("original", JSON.stringify(toShuffle))

4 Comments

That code is pure genius. The way the sort method works! Mind blown.
Also, just fwi. you have 2 unneeded next lines. You can simply do this: return a.map(i => Array.isArray(i) ? shuffle(i) : i).sort(i => ~~(Math.random() * 2) - 1);
Oh, sure, this was for easier to understand how it works, on-liners are not practical for education purposes ;)
Thats why they look so cool :) shuffle=a=>a.map(i=>Array.isArray(i)?shuffle(i):i).sort(i=>~~(Math.random()*2)-1);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.