Сгенерируйте два не повторяющихся случайных числа в диапазоне с помощью Javascript - сосредоточьтесь на производительности скорости

Я хочу сгенерировать 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]];
    }
}

Вы можете объявить переменные вне цикла for, а затем переназначить их внутри цикла for. Как/где вы проводите тесты производительности?

Rickard Elimää 18.11.2022 16:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется медленным"? Почему вы так думаете? Вы проводили бенчмарк? Он слишком медленный для ваших нужд? Но да, есть некоторые моменты, чтобы сделать его правильным и быстрым...

Во-первых, 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 объявлен как объект, но я предполагаю, что вы имеете в виду, что это массив.

EssXTee 18.11.2022 16:23

Отличный ответ! Также обратите внимание, что если длина массива ограничена 4 или небольшим числом, массивы, из которых можно выбрать y, можно легко перечислить. { 0: [1,2,3,4], 1: [0,2,3,4], ...}

danh 18.11.2022 16:29

оценка: 6421931, круто!

Tom Fan 18.11.2022 16:34

@TomFan - любопытно, сильно ли помогает моя идея (поиск объекта или 1 шаг в случайном порядке). Если вам это нравится, пожалуйста, напишите здесь оценку этой идеи.

danh 18.11.2022 16:36

заменить: a = Math.random() * 5 | 0, b = Math.random() * 4 | 0, счет 6579393, быстрее

Tom Fan 18.11.2022 17:06

@danh для такого небольшого количества возможностей (всего 20 разных пар) вы также можете перечислить их все заранее, например [[0,1],[0,2], ..., [1,0],[1,2],...,[5,4]], а затем в цикле просто выбрать одну из пар случайным образом. В зависимости от того, сколько существует разных пар, сколько значений вам нужно и какой генератор случайных чисел вы используете, это также может быть быстрее. Но опять же, это должно быть определено эталоном

derpirscher 19.11.2022 09:25

Другие вопросы по теме