TL;DR
Когда у вас есть список элементов, например: [a, b, c], и вы хотите получить, например, их линейное распределение с помощью обычной функции .random(), просто создайте ряд элементов в этом списке. в линейном распределении: [a, b, b, c, c, c], а затем получить .random() из этого нового списка — и вы получите результат в линейном распределении:
Вы можете сделать более жесткий или более мягкий угол, добавляя больше или меньше элементов для каждого следующего шага, например:
- Мягче 45*: [a, b, c, c]
- Ровно 45*: [а, б, б, в, в, в]
- Тверже 45*: [a, b, b, b, c, c, c, c, c, c]
И это применимо не только к линейным, но и к любым типам профилей: нормальному распределению, экспоненте, квадрату и т. д. — каждый профиль, каждую кривую можно эмулировать с помощью простой функции .random().
Как я пришел к этому
Я разрабатываю Приложение Product Analytics и оно имеет демо-режим. И у него есть санки (древовидная) диаграмма. Но когда я заполнил диаграмму данными .random(), это выглядело глупо, нереально и неинтересно — высота каждой ветки была примерно одинаковой (что означает: использовали одинаковую по сравнению друг с другом):
Я хотел иметь нормальное распределение для этой диаграммы, чтобы некоторые элементы были узкими, а другие широкими — чтобы было интереснее смотреть и играть с ними. Но в ванильном JavaScript нет встроенной функции для нормального распределения. Вместо этого — длинная дискуссионная ветка на StackOverflow.
Глядя на график нормального распределения, я в конце концов пришел к мысли, что эти вертикальные полосы представляют собой повторение значений X. А это значит, что вместо того, чтобы иметь только одно значение для каждого X в массиве, я могу иметь N значений для каждого X в массиве, а затем передавать функцию .random() среди элементов этого массива — и я получу то, что хочу: случайное, но в той форме, которую я хотел.
Итак, я сделал эту модификацию — увеличил количество элементов:
- исходный список: [а, б, в, г, д]
- обычный список распределения: [a, b, b, c, c, c, c, c, d, d, e]
И это сработало:
Видеть? Насколько интересна эта диаграмма по сравнению с оригинальной .random()!
А если мы поместим данные в таблицу, отсортировав значения от максимального к минимальному, то мы увидим, что половинки «колоколообразной кривой» нормального распределения:
Половина кривой из-за сортировки: она сводит все на одну сторону, делая исходную кривую в два раза шире.
Вот почему, когда я хотел смоделировать пользователей и сделать линейную симуляцию, я сделал симуляцию таким же образом и получил это:
А все вместе, вся картина теперь выглядит так:
- нормальное распределение для диаграммы Санки (дерево) и таблицы ниже с левой стороны,
- линейное распределение для UserID в центре,
- и постоянное простое распределение .random() во времени справа:
И все это делается простой и одинаковой единственной функцией .random().
Исходный код для JavaScript
- "Нормальное распределение"
- Линейное распределение
Бонус
Только для тех, кто дочитал до конца!
Поскольку массивы могут быть сложными и тяжелыми, умножение их элементов может дорого стоить вам с точки зрения потребления оперативной памяти. Поэтому вместо умножения самих элементов умножайте их идентификаторы:
- оригинал: [а, б, в]
- линейная «плохая практика»: [a, b, b, c, c, c]
- линейная «хорошая практика»: [0, 1, 1, 2, 2, 2] — идентификаторы для a, b и c
и получить .random() из массива идентификаторов, а затем получить исходный элемент из исходного массива по этому идентификатору.
Надеюсь, вам понравилось и вы весело провели время!