Я пытаюсь отсортировать несколько массивов внутри массива (который также необходимо перетасовать). Упрощенный пример:
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],
// ...
// ]
Это должно быть гибким, поэтому любое количество массивов с любым количеством значений должно быть допустимым.
Вот что я пробовал:
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.info("Shuffled: " + shuffle([
[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1]
]))Но это не работает, как задумано. Это более простой способ сделать это? Или мой код правильный и просто глючит.
Я не понимаю, что вы делаете в блоке else. Вы удаляете текущий элемент массива, но никогда не возвращаете его обратно.
@Barmar Я удаляю элемент e из массива, а затем добавляю его обратно в случайном месте.
Нет, ты не такой. Когда вы вырезаете элемент e, a[e] становится элементом, который раньше был a[e+1]. Итак, вы перемещаете это в случайное положение. Вы никогда не добавите обратно оригинал a[e].
Если вы хотите поменять местами два элемента массива, сделайте temp = a[e]; random = Math.floor(Math.random() * a.length); a[e] = a[random]; a[random] = temp;
Всегда ли он двумерный или это переменные уровни вложенности? Могут ли разные элементы быть вложены в разное количество?
Существует множество реализаций перетасовки по ставкам рыбака. (например, stackoverflow.com/a/46161940/294949) Заимствуйте один (который возвращает новый массив) и сопоставьте его



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ты почти понял. Проблема в том, что вы удаляете один элемент из массива вместо того, чтобы захватить удаленный элемент и поместить его в случайное положение:
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.info(JSON.stringify(shuffle(toShuffle)))
console.info(JSON.stringify(toShuffle))[РЕДАКТИРОВАТЬ] Исходный код не перетасовывал родительский массив, если вам нужно перетасовать все рекурсивно, вы можете использовать это:
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.info("shuffled", JSON.stringify(shuffle(toShuffle)))
console.info("original", JSON.stringify(toShuffle))Этот код просто гениален. Как работает метод сортировки! С ума сошел.
Кроме того, только fwi. у вас есть 2 ненужные следующие строки. Вы можете просто сделать это: return a.map(i => Array.isArray(i) ? shuffle(i) : i).sort(i => ~~(Math.random() * 2) - 1);
О, конечно, это было для того, чтобы было легче понять, как это работает, он-лайнеры не подходят для образовательных целей ;)
Вот почему они так круто выглядят :) shuffle=a=>a.map(i=>Array.isArray(i)?shuffle(i):i).sort(i=>~~(Math.random()*2)-1);
Вы можете использовать Массив.от() для создания нового неглубокого копирования array, а затем перемешать Массив.прототип.сортировка() в сочетании с Math.random().
Код:
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.info('Shuffled:', JSON.stringify(result))
console.info('To shuffle:', JSON.stringify(toShuffle))Мне очень нравится этот ответ, он более простой. Array.from() это круто, просто прочитайте страницу MDN. Очень полезный.
За исключением того, что он не перемешивает сам массив toShuffle...
Вы говорите
it's not working as intended... как выглядит предполагаемый результат?