Генерация случайной строки / символов в JavaScript

1781

Я хочу, чтобы 5-символьная строка состояла из символов, выбранных случайным образом из набора [a-zA-Z0-9].

Какой лучший способ сделать это с помощью JavaScript?

Том Леман
источник
48
Внимание: ни один из ответов не дал true-randomрезультата! Они только pseudo-random. При использовании случайных строк для защиты или безопасности не используйте ни одну из них !!! Попробуйте один из этих API: random.org
Рон ван дер Хейден
48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Муаз Хан
13
Пожалуйста, поместите решение в решение.
Крис
216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Фридрих
12
Обратите внимание, что HTML5 webcrypto randomness API обеспечивает реальную случайность.
mikemaccana

Ответы:

2437

Я думаю, что это будет работать для вас:

function makeid(length) {
   var result           = '';
   var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
   var charactersLength = characters.length;
   for ( var i = 0; i < length; i++ ) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
   }
   return result;
}

console.log(makeid(5));

csharptest.net
источник
117
Это хорошо для коротких строк, но будьте осторожны, использование +=таких строк вызывает поведение O (n ^ 2). Если вы хотите создать более длинные строки, вы должны создать массив отдельных символов и соединить их вместе в конце.
dan_waterworth
97
@dan_waterworth Это, вероятно, не имеет значения почти в любом случае: codinghorror.com/blog/2009/01/…
Алекс Рис
7
@dan_waterworth, на самом деле, +=часто почему-то быстрее, даже используется внутри циклов - jsperf.com/join-vs-concatenation
Конрад Боровски
18
@JonathanPaulson Покажи мне цифры . Смотрите предыдущий комментарий со ссылкой jsperf или jsperf.com/sad-tragedy-of-microoptimization или sitepen.com/blog/2008/05/09/string-performance-an-analysis и т. Д. Кроме того, этот вопрос включает в себя только 5 объединений ,
Алекс Рис
11
@codenamejames Пожалуйста , не используйте это для посола пароля. Это только псевдослучайный, не безопасный. Предполагая, что вы используете Node (я даже не уверен, с чего начать, если вы солите на стороне клиента), используйте cryptoвместо этого.
Гидротермальный
2331

let r = Math.random().toString(36).substring(7);
console.log("random", r);

Примечание: приведенный выше алгоритм имеет следующие недостатки:

  • Он будет генерировать в любом месте от 0 до 6 символов из-за того, что конечные нули удаляются при строковом вычислении с плавающей запятой.
  • Это глубоко зависит от алгоритма, используемого для преобразования чисел с плавающей запятой, который ужасно сложен. (См. Статью «Как правильно печатать числа с плавающей точкой» .)
  • Math.random()может выдавать предсказуемый («случайный», но не случайный) результат в зависимости от реализации. Результирующая строка не подходит, когда вам нужно гарантировать уникальность или непредсказуемость.
  • Даже если он произвел 6 равномерно случайных, непредсказуемых символов, вы можете ожидать появления дубликата после генерации всего около 50 000 строк из-за парадокса дня рождения . (sqrt (36 ^ 6) = 46656)
двойное нажатие
источник
276
Math.random().toString(36).substr(2, 5), потому что .substring(7)заставляет его быть длиннее 5 символов. Полный балл, все же!
дракон
81
@Scoop toStringМетод числового типа в javascript принимает необязательный параметр для преобразования числа в заданную базу. Например, если вы передадите два, вы увидите, что ваш номер представлен в двоичном виде. Как и в шестнадцатеричном (основание 16), основание 36 использует буквы для представления цифр за пределами 9. Преобразовав случайное число в основание 36, вы получите кучу, казалось бы, случайных букв и цифр.
Крис Бейкер
76
Выглядит красиво, но в некоторых случаях это создает пустую строку! Если случайный возврат 0, 0,5, 0,25, 0,125 ... приведет к пустой или короткой строке.
Гертас
68
@gertas Этого можно избежать(Math.random() + 1).toString(36).substring(7);
Джордж Райт
84
Парень, это практически бесполезно. Запустите его всего 1000000 раз, и вы получите около 110000 повторений: var values ​​= {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (values ​​[val]) {duplicateCount ++; } значения [val] = 1; я ++; } console.log («ВСЕГО ДУБЛИКАТОВ», duplicateCount);
hacklikecrack
463

Math.random это плохо для такого рода вещей

Опция 1

Если вы можете сделать это на стороне сервера , просто используйте криптомодуль -

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

Результирующая строка будет в два раза длиннее случайных байтов, которые вы генерируете; каждый байт, закодированный в шестнадцатеричный код, состоит из 2 символов. 20 байтов будут 40 символами гекса.


Вариант 2

Если вам нужно сделать это на стороне клиента , возможно, попробуйте модуль uuid -

var uuid = require("uuid");
var id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

Вариант 3

Если вам нужно сделать это на стороне клиента и вам не нужно поддерживать старые браузеры, вы можете сделать это без зависимостей -

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
  return ('0' + dec.toString(16)).substr(-2)
}

// generateId :: Integer -> String
function generateId (len) {
  var arr = new Uint8Array((len || 40) / 2)
  window.crypto.getRandomValues(arr)
  return Array.from(arr, dec2hex).join('')
}

console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"

console.log(generateId(20))
// "c1a050a4cd1556948d41"


Для получения дополнительной информации о crypto.getRandomValues-

crypto.getRandomValues()Метод позволяет получить криптографически сильные случайные значения. Массив, заданный в качестве параметра, заполняется случайными числами (случайными в своем криптографическом значении).

Вот небольшой пример консоли -

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]

> window.crypto
Crypto { subtle: SubtleCrypto }

> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed

> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]

Для поддержки IE11 вы можете использовать -

(window.crypto || window.msCrypto).getRandomValues(arr)

Для покрытия браузера см. Https://caniuse.com/#feat=getrandomvalues

Спасибо
источник
4
Точно. Хотя UUID отлично подходит для назначения идентификатора вещи, использование его в качестве строки случайных символов не является хорошей идеей по этой (и, вероятно, другим) причинам.
Wmassingham
2
Нет необходимости .map()в варианте 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Спасибо за то, что познакомили меня с этими функциями :-)
Фред Гандт
6
В ответе следует упомянуть, что для работы варианта 2 также необходим node.js, это не чистый javascript.
Эско
5
Будучи более криптографически безопасным, на самом деле это не удовлетворяет требованиям вопроса, поскольку выводит только 0-9 и af (шестнадцатеричное), а не 0-9, az, AZ.
qJake
1
Разве requireмодуль не может быть использован только на стороне сервера?
aJetHorn
173

Коротко, просто и надежно

Возвращает ровно 5 случайных символов, в отличие от некоторых самых популярных ответов, найденных здесь.

Math.random().toString(36).substr(2, 5);
Серебряное Кольцо
источник
9
Что делать, если Math.random().toString(36)возвращает число менее 5 символов?
Михаил Литвин
3
Ну, это интересное обвинение от @ Aperçu, я не говорю, что я изобрел решение, но я использую его в своих проектах уже много лет. И это не имеет ничего общего с упомянутым вами комментарием. И я совершенно уверен, что в SO важна самая полезная информация в нужном месте, и даже если она уже существует в каком-то другом месте. К счастью, кажется, что по крайней мере 51 человек нашел этот ответ полезным, пожалуйста!
Серебро Рингви
3
Чтобы избежать получения пустой строки в случае, если Math.random () возвращает 0, вы можете использоватьfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep
5
@rinogo Math.random () может вернуть 0, но не 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep
6
Я запускал этот код 1 000 000 000 раз и до сих пор не получил пустую строку: jsfiddle.net/mtp5730r Я бы сказал, что вы совершенно не можете получить пустую строку.
MacroMan
157

Вот улучшение превосходного ответа даблтапа . У оригинала есть два недостатка, которые рассматриваются здесь:

Во-первых, как уже упоминали другие, существует небольшая вероятность создания коротких строк или даже пустой строки (если случайное число равно 0), что может нарушить работу вашего приложения. Вот решение:

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)

Во-вторых, и оригинал, и приведенное выше решение ограничивают размер строки N до 16 символов. Следующее вернет строку размера N для любого N (но учтите, что использование N> 16 не увеличит случайность и не уменьшит вероятность столкновений):

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)

Объяснение:

  1. Выберите случайное число в диапазоне [0,1), то есть от 0 (включительно) до 1 (исключая).
  2. Преобразуйте число в строку base-36, т.е. используя символы 0-9 и az.
  3. Подушка с нулями (решает первый вопрос).
  4. Отрежьте ведущий '0.' префикс и дополнительные нули дополнения.
  5. Повторите строку достаточное количество раз, чтобы в ней было хотя бы N символов (путем объединения пустых строк с более короткой случайной строкой, используемой в качестве разделителя).
  6. Вырезать ровно N символов из строки.

Дальнейшие мысли:

  • Это решение не использует заглавные буквы, но почти во всех случаях (без каламбура) это не имеет значения.
  • Максимальная длина строки при N = 16 в исходном ответе измеряется в Chrome. В Firefox это N = 11. Но, как объяснено, второе решение заключается в поддержке любой запрашиваемой длины строки, а не в добавлении случайности, поэтому это не имеет большого значения.
  • Все возвращаемые строки имеют одинаковую вероятность быть возвращенными, по крайней мере, если результаты, возвращаемые Math.random (), распределены равномерно (в любом случае это не случайность с криптографической стойкостью).
  • Не все возможные строки размера N могут быть возвращены. Во втором решении это очевидно (поскольку строка меньшего размера просто дублируется), но и в исходном ответе это верно, поскольку при преобразовании в base-36 последние несколько битов могут не являться частью исходных случайных битов. В частности, если вы посмотрите на результат Math.random (). ToString (36), вы заметите, что последний символ распределен неравномерно. Опять же, почти во всех случаях это не имеет значения, но мы нарезаем последнюю строку с начала, а не с конца случайной строки, чтобы не затрагивать короткие строки (например, N = 1).

Обновить:

Вот пара других однострочников в функциональном стиле, которые я придумал. Они отличаются от решения выше тем, что:

  • Они используют явный произвольный алфавит (более общий и подходящий для исходного вопроса, который задавался как прописными, так и строчными буквами).
  • Все строки длины N имеют одинаковую вероятность быть возвращенными (т.е. строки не содержат повторений).
  • Они основаны на функции карты, а не на приеме toString (36), что делает их более простыми и понятными.

Итак, скажем, ваш алфавит выбора

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Тогда эти два эквивалента друг другу, так что вы можете выбрать тот, который является более интуитивным для вас:

Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

а также

Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

Редактировать:

Я, кажется, как Qubyte и Мартейн де Миллиано придумали решения, аналогичные последним (слава!), я почему-то упустил. Так как они не выглядят короткими с первого взгляда, я все равно оставлю это здесь на тот случай, если кто-то действительно хочет однострочника :-)

Кроме того, во всех решениях заменили 'new Array' на 'Array', чтобы сбрить еще несколько байтов.

amichair
источник
Почему бы просто не добавить 1? (Math.random()+1).toString(36).substring(7);
emix
Потому что добавление 1 не решает ни одну из двух обсуждаемых здесь проблем. Например, (1) .toString (36) .substring (7) создает пустую строку.
amichair
Использование Math.random().toString(36).substring(2,7)дает ожидаемый результат, который больше похож на.substring(2, n+2)
Джозеф Рекс
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
Мухаммед Умер
Это замечательно, но при исполнении в Firefox с N = 16 последние ~ 6 цифр в конечном итоге становятся равными нулю ... (Но, тем не менее, это удовлетворяет желанию ОП получить 5 случайных символов.)
Эдвард Ньюэлл
128

Самое компактное решение, потому что sliceкороче substring. Вычитание из конца строки позволяет избежать символа с плавающей точкой, сгенерированного randomфункцией:

Math.random().toString(36).slice(-5);

или даже

(+new Date).toString(36).slice(-5);

Обновление: добавлен еще один подход с использованием btoaметода:

btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);

// Using Math.random and Base 36:
console.log(Math.random().toString(36).slice(-5));

// Using new Date and Base 36:
console.log((+new Date).toString(36).slice(-5));

// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));

// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(-7, -2));
console.log(btoa(+new Date).substr(-7, 5));

Валентин Подкаменный
источник
Math.random().toString(36).slice(-5);- Что, если Math.random()вернется 0.0?
рентген
@ Рентген, ты получишь "0";)
Валентин Подкаменный
2
Точно. ;) А если Math.random()возвращает, 0.5то результат есть "0.i". Не уверен, что есть другие крайние случаи. Просто хотел отметить, что это неправильный ответ на вопрос (5 ​​символов из [a-zA-Z0-9]).
рентгеновское изображение
2
@ x-ray, я не собираюсь говорить, что это правильный ответ, я просто говорю, что это компактная версия ответа @doubletap выше. Я лично использую, (+new Date + Math.random())чтобы предотвратить это дело. В любом случае, спасибо за примечание.
Валентин Подкаменный
1
Эта. Я не знаю, почему другие ответы требуют так много кода
Джон Ktejik
100

Как то так должно работать

function randomString(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var randomString = '';
    for (var i = 0; i < len; i++) {
        var randomPoz = Math.floor(Math.random() * charSet.length);
        randomString += charSet.substring(randomPoz,randomPoz+1);
    }
    return randomString;
}

Позвоните с набором символов по умолчанию [a-zA-Z0-9] или отправьте по своему усмотрению:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
CaffGeek
источник
Вариант примера здесь можно найти здесь: mediacollege.com/internet/javascript/number/random.html
Дэвид
1
может также просто уменьшить lenпрямо в whileцикле
drzaus
Спасибо, я только что опубликовал ниже вариант coffeescript этого примера: stackoverflow.com/a/26682781/262379
Dinis Cruz
Если они будут использоваться публично, то вам, вероятно, следует удалить гласные. Немного меньше энтропии, но намного безопаснее, так как вы не можете генерировать слова, которые могут оскорбить людей. Вот почему мне это нравится, так как я могу отправить свою собственную строку символов. Отличная работа.
Нейт Банни
Довольно хардкор, работал для меня, спасибо!
Заки Мохаммед
73

Более новая версия с оператором распространения es6 :

[...Array(30)].map(() => Math.random().toString(36)[2]).join('')

  • Это 30произвольное число, вы можете выбрать любую желаемую длину токена
  • 36Максимальное число радикс вы можете перейти к numeric.toString () , что означает все номера и азимуту строчные буквы
  • 2Используются , чтобы выбрать 3 - й индекс от случайной строки , которая выглядит следующим образом : "0.mfbiohx64i"мы могли бы взять любой индекс после0.
Или Дуань
источник
Могли бы вы объяснить? Особенно, почему вы передаете 36 toString () и почему вы выбираете третий элемент?
vuza
5
это самое лучшее решение
преодолевающий
хорошо, но это решение не включает символы [AZ] по запросу, только [a-z0-9]
Науэль Греко
72

function randomstring(L) {
  var s = '';
  var randomchar = function() {
    var n = Math.floor(Math.random() * 62);
    if (n < 10) return n; //1-10
    if (n < 36) return String.fromCharCode(n + 55); //A-Z
    return String.fromCharCode(n + 61); //a-z
  }
  while (s.length < L) s += randomchar();
  return s;
}
console.log(randomstring(5));

Kennebec
источник
Мне нравится это лучше всего. Вы можете легко изменить, чтобы принимать дополнительные параметры и возвращать только числа, понижения или ограничения. Я не думаю, что ультра-сжатый стиль необходимwhile(s.length< L) s+= randomchar();
mastaBlasta
3
И while(L--)сделаем это
vsync
1
Лучше использовать более надежный 'A'.charCodeAt(0), чем магический номер 55(и аналогично для 61). Тем более что на моей платформе все равно магическое число, которое возвращается 65. Этот код также лучше документирует себя.
Грумдриг
Я создал вариант вашей реализации, оптимизированный для минимизации (на 46 байт меньше): stackoverflow.com/a/52412162
Waruyama
Удачи в отладке этого @Waruyama. Вот для чего предназначен веб-пакет!
Дилан Уотсон
61

Генератор случайных строк (буквенно-цифровой | буквенно-цифровой)

/**
 * Pseudo-random string generator
 * http://stackoverflow.com/a/27872144/383904
 * Default: return a random alpha-numeric string
 * 
 * @param {Integer} len Desired length
 * @param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
 * @return {String}
 */
function randomString(len, an) {
  an = an && an.toLowerCase();
  var str = "",
    i = 0,
    min = an == "a" ? 10 : 0,
    max = an == "n" ? 10 : 62;
  for (; i++ < len;) {
    var r = Math.random() * (max - min) + min << 0;
    str += String.fromCharCode(r += r > 9 ? r < 36 ? 55 : 61 : 48);
  }
  return str;
}

console.log(randomString(10));      // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"


В то время как вышесказанное использует дополнительные проверки для желаемых A / N, A, N выходов , давайте разберем их с основными (только буквенно-цифровыми) для лучшего понимания:

  • Создайте функцию, которая принимает аргумент (желаемая длина случайного результата String)
  • Создайте пустую строку как var str = ""; для объединения случайных символов
  • Внутри цикла создайте randпорядковый номер от 0 до 61 (0..9 + A..Z + a..z = 62)
  • Создайте условную логику для Adjust / Fixrand (так как это 0..61), увеличивая ее на некоторое число (см. Примеры ниже), чтобы получить верное CharCodeчисло и соответствующий символ.
  • Внутри цикла объединить strсString.fromCharCode( incremented rand )

Давайте изобразим диапазоны таблицы символов ASCII :

_____0....9______A..........Z______a..........z___________  Character
     | 10 |      |    26    |      |    26    |             Tot = 62 characters
    48....57    65..........90    97..........122           CharCode ranges

Math.floor( Math.random * 62 )дает диапазон от 0..61(что нам нужно).
Давайте исправим случайность, чтобы получить правильные диапазоны charCode :

      |   rand   | charCode |  (0..61)rand += fix            = charCode ranges |
------+----------+----------+--------------------------------+-----------------+
0..9  |   0..9   |  48..57  |  rand += 48                    =     48..57      |
A..Z  |  10..35  |  65..90  |  rand += 55 /*  90-35 = 55 */  =     65..90      |
a..z  |  36..61  |  97..122 |  rand += 61 /* 122-61 = 61 */  =     97..122     |

Условная операция логика из приведенных выше таблиц:

   rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand +=  true  ? (  true   ? 55 else 61 ) else 48 ;

Из приведенного выше объяснения вот итоговый буквенно-цифровой фрагмент :

function randomString(len) {
  var str = "";                                // String result
  for (var i = 0; i < len; i++) {              // Loop `len` times
    var rand = Math.floor(Math.random() * 62); // random: 0..61
    var charCode = rand += rand > 9 ? (rand < 36 ? 55 : 61) : 48; // Get correct charCode
    str += String.fromCharCode(charCode);      // add Character to str
  }
  return str; // After all loops are done, return the concatenated string
}

console.log(randomString(10)); // i.e: "7GL9F0ne6t"

Или если вы будете:

const randomString = (n, r='') => {
  while (n--) r += String.fromCharCode((r=Math.random()*62|0, r+=r>9?(r<36?55:61):48));
  return r;
};

console.log(randomString(10))

Роко С. Бульян
источник
33

Самый простой способ:

(new Date%9e6).toString(36)

Это генерирует случайные строки из 5 символов на основе текущего времени. Пример вывода - 4mtxjили 4mv90или4mwp1

Проблема в том, что если вы вызываете его два раза в одну и ту же секунду, он генерирует одну и ту же строку.

Более безопасный способ:

(0|Math.random()*9e6).toString(36)

Это сгенерирует случайную строку из 4 или 5 символов, всегда отличающихся. Пример вывода похож на 30jzmили 1r591или4su1a

В обоих случаях первая часть генерирует случайное число. .toString(36)Часть отбрасывать число в base36 (alphadecimal) представления о нем.

MasqueradeCircus
источник
Я не совсем уверен, как это отвечает на вопрос; Это 7-летний вопрос со многими действительными ответами уже. Если вы решите предоставить новый ответ, вам следует проявить особую осторожность, чтобы убедиться, что ваш ответ хорошо объяснен и задокументирован.
Claies
1
Если вы используете дату, почему бы вам просто не использовать это как:(+new Date).toString(36)
старший преподаватель
Мне нравится ваше решение для случайных чисел, но 9e6 дает только 9 миллионов возможностей из 60,4 миллионов для 5 цифр (36 ^ 5), так что вы можете заменить его, (0|Math.random()*6.04e7).toString(36)чтобы покрыть его.
Le Droid
1
Я хотел длинную случайную строку с подпрограммой с кратким изложением возможных вариантов (для демонстрации кода), которая не должна быть удивительной с точки зрения криптографии, просто создайте некоторый приятный случайный визуальный «пух». Мне больше нравится этот ответ (ваш второй), так что спасибо. Мои два цента: я могу побить его для краткости одним нажатием клавиши меньше, и это, как правило , производят 13 случайных символов (без периода) (Math.random()*1e20).toString(36).
Эндрю Виллемс
у меня есть одно затруднение с этим ответом - он не будет использовать [AZ], как в оригинальном вопросе.
user.friendly
22

Вот несколько простых лайнеров. + Изменитьnew Array(5) чтобы установить длину.

Включая 0-9a-z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})

Включая 0-9a-zA-Z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
bendytree
источник
20

Я знаю, что все уже поняли это правильно, но я чувствовал, что хочу попробовать этот способ самым легким способом (легкий на код, а не на процессор):

function rand(length, current) {
  current = current ? current : '';
  return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}

console.log(rand(5));

Требуется немного времени, чтобы обернуть голову, но я думаю, что это действительно показывает, каков классный синтаксис javascript.

Родерик
источник
20
Если вы пытаетесь сделать код коротким, зачем писать, current = current ? current : '';когда вы можете писать current = current || '';
CaffGeek
9
поскольку здесь мы говорим о микрооптимизации, я бы фактически предложил полностью пропустить присвоение переменной, если не нужно:current || (current = '');
Томас Хейманн
Попытка микрооптимизации при использовании «хорошего», но рекурсивного алгоритма траты ресурсов не имеет смысла :-) Цикл for по-прежнему является лучшим в Javascript и превосходит рекурсию до тех пор, пока не достигнут действительно значительный прогресс в оптимизации кода времени выполнения.
Мёрре
17

Если вы используете Lodash или Underscore , то это так просто:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
Vineet
источник
6
Lodash использует_.sampleSize('asdfgh',5).join('')
Марло
2
На самом деле это не очень хорошее решение, потому что каждый документ имеет уникальный индекс. Это означает, что это не случайно, так как ни один персонаж не может / никогда не повторится.
random_user_name
16

Для удовлетворения требования [a-zA-Z0-9] и длины = 5 используйте

btoa(Math.random()).substr(5, 5);

Будут встречаться строчные буквы, прописные буквы и цифры.

Серхио Кабрал
источник
1
Я предполагаю, что Math.random () может привести к строке base64 со слишком небольшим количеством символов.
Лейф
14

В случае, если кто-то заинтересован в одной строке (хотя для вашего удобства она не отформатирована как таковая), которая выделяет память сразу (но учтите, что для небольших строк это действительно не имеет значения), вот как это сделать:

Array.apply(0, Array(5)).map(function() {
    return (function(charset){
        return charset.charAt(Math.floor(Math.random() * charset.length))
    }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')

Вы можете заменить 5на длину строки, которую вы хотите. Спасибо @AriyaHidayat в этом посте за решение mapфункции, не работающей с разреженным массивом, созданным Array(5).

Мартейн де Миллиано
источник
13
Каждая javascript-программа является «однострочной», если вы отформатируете ее так
hacklikecrack
13

Вот метод, который я создал.
Это создаст строку, содержащую как прописные, так и строчные буквы.
Кроме того, я включил функцию, которая будет также создавать буквенно-цифровую строку.

Рабочие примеры:
http://jsfiddle.net/greatbigmassive/vhsxs/ (только альфа)
http://jsfiddle.net/greatbigmassive/PJwg8/ (буквенно-цифровой)

function randString(x){
    var s = "";
    while(s.length<x&&x>0){
        var r = Math.random();
        s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65));
    }
    return s;
}

Обновление Июль 2015
Это делает то же самое, но имеет больше смысла и включает в себя все буквы.

var s = "";
while(s.length<x&&x>0){
    v = Math.random()<0.5?32:0;
    s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v)));
}
Адам
источник
С помощью этой функции вы никогда не сможете получить заглавную букву больше, чем «M», или строчную букву меньше, чем «n».
erkanyildiz
В самом деле? ооо! вероятно, будет проверять это больше тогда. Хм, однако, учитывая, что это случайная строка, и нам все равно, какие буквы в ней (если они случайные), тогда она все равно делает то, что мы хотим, и это все, что имеет значение, но да, обеспечит обновить, спасибо.
Адам
12

Предполагая, что вы используете underscorejs , можно элегантно сгенерировать случайную строку всего за две строки:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
TikTak
источник
6
Это позволит возвращаемому значению иметь все уникальные символы. Кроме того, длина строки ограничена возможной длиной переменной.
Ефу
10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Науэль Греко
источник
Простое, чистое решение
Марк Свардстрем
Это заслуживает большего +1
Валид Аммар
10

Быстрый и улучшенный алгоритм. Не гарантирует форму (см. Комментарии).

function getRandomId(length) {
    if (!length) {
        return '';
    }

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let array;

    if ('Uint8Array' in self && 'crypto' in self && length <= 65536) {
        array = new Uint8Array(length);
        self.crypto.getRandomValues(array);
    } else {
        array = new Array(length);

        for (let i = 0; i < length; i++) {
            array[i] = Math.floor(Math.random() * 62);
        }
    }

    let result = '';

    for (let i = 0; i < length; i++) {
        result += possible.charAt(array[i] % 62);
    }

    return result;
}
ярослав
источник
2
Отличный ответ, но вероятность не одинакова. Есть 62 возможных символа и crypto.getRandomValuesвозвращает одно из 256 уникальных значений. Поскольку 256 не делится на 62, вероятность того, что персонажи получат AH, несколько выше. Я думаю, что лучшим решением будет сделать то, что сделал YouTube, и просто добавить 2 дополнительных символа (возможно, -и _) в кодировку. Во всяком случае, отличная работа - этот ответ требует гораздо больше любви :)
TeWu
добавление - и _ - отличная идея, так как она предоставит вам полный url-безопасный набор base64
cowbert
8

Проблема с ответами на вопросы «Мне нужны случайные строки» (на любом языке) состоит в том, что практически каждое решение использует некорректную первичную спецификацию длины строки . Сами вопросы редко показывают, зачем нужны случайные строки, но я бы сказал, что вам редко нужны случайные строки длины, скажем, 8. Что вам обязательно нужно, так это некоторое количество уникальных строк , например, для использования в качестве идентификаторов для каких-то целей.

Есть два основных способа получения строго уникальных строк: детерминистично (что не случайно) и хранить / сравнивать (что обременительно). Что мы делаем? Мы отдаем призрак. Вместо этого мы используем вероятностную уникальность . То есть мы признаем, что существует некоторый (хотя и небольшой) риск того, что наши строки не будут уникальными. Это где понимание вероятности столкновения и энтропии полезно .

Поэтому я перефразирую неизменную потребность как нужное количество строк с небольшим риском повторения. В качестве конкретного примера предположим, что вы хотите создать 5 миллионов идентификаторов. Вы не хотите хранить и сравнивать каждую новую строку, и вы хотите, чтобы они были случайными, поэтому вы принимаете некоторый риск повторения. Например, допустим, что риск повторения меньше 1 в триллионе. Так какая длина строки вам нужна? Ну, этот вопрос недостаточно конкретизирован, поскольку зависит от используемых символов. Но что более важно, это ошибочно. Вам нужно указать энтропию строк, а не их длину. Энтропия может быть напрямую связана с вероятностью повторения в некотором количестве строк. Длина строки не может.

И здесь может помочь библиотека вроде EntropyString . Чтобы сгенерировать случайные идентификаторы с шансом повторения менее 1 на триллион в 5 миллионах строк, используйте entropy-string:

import {Random, Entropy} from 'entropy-string'

const random = new Random()
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

"44hTNghjNHGGRHqH9"

entropy-stringпо умолчанию использует набор из 32 символов. Существуют и другие предопределенные наборы символов, и вы также можете указать свои собственные символы. Например, генерация идентификаторов с той же энтропией, что и выше, но с использованием шестнадцатеричных символов:

import {Random, Entropy, charSet16} from './entropy-string'

const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

"27b33372ade513715481f"

Обратите внимание на разницу в длине строки из-за разницы в общем количестве символов в используемом наборе символов. Риск повторения в указанном количестве потенциальных строк одинаков. Длина строки не. И, что лучше всего, риск повторения и потенциальное количество строк явно. Больше не нужно гадать с длиной строки.

динго небо
источник
7
function randomString (strLength, charSet) {
    var result = [];

    strLength = strLength || 5;
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    while (--strLength) {
        result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
    }

    return result.join('');
}

Это настолько чисто, насколько это возможно. Это тоже быстро, http://jsperf.com/ay-random-string .

Gajus
источник
Для меня это всегда генерирует случайные строки с strLength - 1: - /
xanderiel
3
Переключение с, --strLengthчтобы strLength--исправить это для меня.
xanderiel
7

Вы можете просмотреть массив элементов и рекурсивно добавить их в строковую переменную, например, если вы хотите случайную последовательность ДНК:

function randomDNA(len) {
  len = len || 100
  var nuc = new Array("A", "T", "C", "G")
  var i = 0
  var n = 0
  s = ''
  while (i <= len - 1) {
    n = Math.floor(Math.random() * 4)
    s += nuc[n]
    i++
  }
  return s
}

console.log(randomDNA(5));

Энди
источник
7

Один лайнер:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Эндрю
источник
Чтобы сделать его короче, измените аргумент Array(15)на меньшее значение. Например: Array(4).
Андрей
Я действительно люблю это решение, простое и понятное. Он генерирует 15 случайных чисел от 0 до 1, генерирует шестнадцатеричное число, а затем удаляет первые два символа. Наконец это объединяет их всех вместе.
Сиския
6

Я не нашел чистого решения для поддержки как строчных, так и прописных букв.

Поддержка только в нижнем регистре:

Math.random().toString(36).substr(2, 5)

Основываясь на этом решении для поддержки строчных и прописных букв:

Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');

Измените значение 5в substr(2, 5)нужной длине.

ravishi
источник
5

Это работает точно

<script language="javascript" type="text/javascript">
function randomString() {
 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
 var string_length = 8;
 var randomstring = '';
 for (var i=0; i<string_length; i++) {
  var rnum = Math.floor(Math.random() * chars.length);
  randomstring += chars.substring(rnum,rnum+1);
 }
 document.randform.randomfield.value = randomstring;
}
</script>
Вигнеш
источник
5

Как насчет этого: Date.now().toString(36) Не очень случайный, но короткий и совершенно уникальный каждый раз, когда вы называете это.

Swergas
источник
1
К сожалению, это не будет уникальным, поскольку Date.now()имеет разрешение только в миллисекундах. Например, при запуске в простом цикле вы получите много дубликатов. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); },
Nate
5

Буквенно-цифровые символы без учета регистра:

function randStr(len) {
  let s = '';
  while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length);
  return s;
}

// usage
console.log(randStr(50));

Преимущество этой функции заключается в том, что вы можете получить произвольную строку разной длины, и она обеспечивает длину строки.

Чувствительный к регистру все символы:

function randStr(len) {
  let s = '';
  while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
  return s;
}

// usage
console.log(randStr(50));

Пользовательские символы

function randStr(len, chars='abc123') {
  let s = '';
  while (len--) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

// usage
console.log(randStr(50));
console.log(randStr(50, 'abc'));
console.log(randStr(50, 'aab')); // more a than b

Али
источник
Этот ответ больше подходит для моего варианта использования. Было бы здорово, если бы вы могли добавить var possibleподобное в принятый ответ, чтобы результат функции был более настраиваемым.
Денис. Саболотни
4

Генерировать 10 символов длинной строки. Длина задается параметром (по умолчанию 10).

function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;

for(i=0; i<len; i++) {
    switch(Math.floor(Math.random()*3+1)) {
        case 1: // digit
            str += (Math.floor(Math.random()*9)).toString();
        break;

        case 2: // small letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
        break;

        case 3: // big letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
        break;

        default:
        break;
    }
}
return str;
}
ropsiU
источник
4

Вы можете использовать Coderain . Это библиотека для генерации случайных кодов по заданному шаблону. Используйте #в качестве заполнителя для прописных и строчных букв, а также цифр:

var cr = new CodeRain("#####");
console.log(cr.next());

Есть и другие заполнители, такие как Aзаглавные буквы или9 цифры.

Что может быть полезным, так это .next() всегда даст вам уникальный результат, поэтому вам не придется беспокоиться о дубликатах.

Вот демонстрационное приложение, которое генерирует список уникальных случайных кодов .

Полное раскрытие: я автор Coderain.

Лукаш Виктор
источник
НЕТ НЕТ НЕТ - используйте нативные методы.