Я хочу сгенерировать 1000 объектов и поместить их в массив стека.
Внутри объекта есть 2 случайных и не повторяющихся числа.
Диапазон от 0 до 4.
Я хочу найти метод с лучшими показателями скорости.
оценка тестов производительности: 34664
const stack = [];
for (let i = 0; i < 1000; i++) {
const range = [0, 1, 2, 3, 4];
let r = Math.round(Math.random() * (range.length - 1));
let x = range[r];
range.splice(r, 1);
let y = range[Math.round(Math.random() * (range.length - 1))];
stack.push({ x: x, y: y });
}
оценка теста производительности: 41618
const stack = [];
for (let i = 0; i < 1000; i++) {
let range = [0, 1, 2, 3, 4];
let shuffled = shuffleArray(range);
let x = shuffled[0];
let y = shuffled[shuffled.length - 1];
stack.push({ x: x, y: y });
}
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
Кажется медленным"? Почему вы так думаете? Вы проводили бенчмарк? Он слишком медленный для ваших нужд? Но да, есть некоторые моменты, чтобы сделать его правильным и быстрым...
Во-первых, slice
здесь неправильно, вы, вероятно, имеете в виду splice
.
Затем вы создаете новый массив на каждой итерации, это дорого. Тем более, если вы тоже splice
делаете это. Лучше было бы, переключая элементы в существующем массиве. И, наконец, вам не нужно вычислять range.length-1
дважды на каждой итерации. Вы знаете, что значения будут 4
и 3
...
Так что я бы сделал это так
let
stack = [],
range = [0,1,2,3,4];
for (let i = 0; i < 1000; i++){
let
a = Math.floor(Math.random()* 5),
b = Math.floor(Math.random()* 4),
x = range[a];
range[a] = range[4];
range[4] = x;
stack.push({ x, y: range[b]});
}
Как это работает:
Существует только один массив со всеми возможными значениями. Сначала выберите два случайных индекса: a
в диапазоне [0, 4]
и b
в диапазоне [0, 3]
. Тогда ваше первое случайное значение — это элемент с индексом a
. Теперь поменяйте местами элемент с индексом a
на последний элемент в массиве. Ваше второе случайное значение теперь является элементом с индексом b
. Эти два значения должны быть разными (даже если a === b
), потому что b
никогда не сможет выбрать самый последний элемент массива. Это простая вариация классического алгоритма "Фишера-Йейтса"...
Небольшое примечание: stack
объявлен как объект, но я предполагаю, что вы имеете в виду, что это массив.
Отличный ответ! Также обратите внимание, что если длина массива ограничена 4 или небольшим числом, массивы, из которых можно выбрать y
, можно легко перечислить. { 0: [1,2,3,4], 1: [0,2,3,4], ...}
оценка: 6421931, круто!
@TomFan - любопытно, сильно ли помогает моя идея (поиск объекта или 1 шаг в случайном порядке). Если вам это нравится, пожалуйста, напишите здесь оценку этой идеи.
заменить: a = Math.random() * 5 | 0, b = Math.random() * 4 | 0, счет 6579393, быстрее
@danh для такого небольшого количества возможностей (всего 20 разных пар) вы также можете перечислить их все заранее, например [[0,1],[0,2], ..., [1,0],[1,2],...,[5,4]]
, а затем в цикле просто выбрать одну из пар случайным образом. В зависимости от того, сколько существует разных пар, сколько значений вам нужно и какой генератор случайных чисел вы используете, это также может быть быстрее. Но опять же, это должно быть определено эталоном
Вы можете объявить переменные вне цикла for, а затем переназначить их внутри цикла for. Как/где вы проводите тесты производительности?