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

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

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

Ответ 1

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

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));

Ответ 2

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

Ответ 3

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"

Ответ 4

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

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

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

Ответ 5

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

Во-первых, как отмечали другие, он имеет небольшую вероятность создания коротких строк или даже пустой строки (если случайное число равно 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)

Пояснение:

  • Выберите случайное число в диапазоне [0,1], то есть между 0 (включительно) и 1 (эксклюзивным).
  • Преобразуйте число в строку базы 36, то есть используя символы 0-9 и a-z.
  • Папка с нулями (решает первую проблему).
  • Отрежьте верхний "0." префикс и лишние нули.
  • Повторите строку достаточно времени, чтобы иметь в ней по крайней мере N символов (путем объединения пустых строк с более короткой случайной строкой, используемой в качестве разделителя).
  • Нарисуйте ровно N символов из строки.

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

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

Update:

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

  • Они используют явный произвольный алфавит (более общий и подходящий для исходного вопроса, который запрашивает как прописные, так и строчные буквы).
  • Все строки длины 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('');

Edit:

Мне кажется, qubyte и Martijn de Milliano придумали решения, подобные последним (kudos!), который я как-то пропустил. Поскольку они не выглядят краткими, я останусь здесь все равно, если кто-то действительно хочет однострочный: -)

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

Ответ 6

Что-то вроде этого должно работать

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');

Ответ 7

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));

Ответ 8

Наиболее компактное решение, поскольку 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));

Ответ 9

Случайный строковый генератор (альфа-числовой | альфа-цифра)

/**
 * RANDOM STRING GENERATOR
 *
 * Info:      http://stackoverflow.com/a/27872144/383904
 * Use:       randomString(length [,"A"] [,"N"] );
 * Default:   return a random alpha-numeric string
 * Arguments: If you use the optional "A", "N" flags:
 *            "A" (Alpha flag)   return random a-Z string
 *            "N" (Numeric flag) return random 0-9 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;
}
randomString(10);        // "4Z8iNQag9v"
randomString(10, "A");   // "aUkZuHNcWw"
randomString(10, "N");   // "9055739230"

Получайте удовольствие. jsBin demo


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

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

Представьте картинку Таблица символов и их диапазоны:

_____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 ;

Если вы следуете приведенному выше объяснению, вы сможете создать этот альфа-цифровой фрагмент:

jsBin demo

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) ); // "7GL9F0ne6t"

Или, если вы:

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

Ответ 10

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

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

  • 30 - произвольное число, вы можете выбрать любую желаемую длину токена
  • 36 - это максимальное число радиуса, которое вы можете передать numeric.toString(), что означает все цифры и строчные буквы az
  • 2 используется для выбора 2-го числа из случайной строки, которая выглядит следующим образом: "0.mfbiohx64i", мы можем взять любой индекс после 0.

Ответ 11

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

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

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

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

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

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

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

В обоих случаях первая часть генерирует случайное число. Часть .toString(36) передала число в базовое36 (буквенно-цифровое) представление.

Ответ 12

Вот несколько простых лайнеров. Измените 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"]();});

Ответ 13

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

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

console.log(rand(5));

Ответ 14

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

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');

Ответ 15

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

Рабочие примеры:
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)));
}

Ответ 16

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

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');

Ответ 17

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

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).

Ответ 18

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

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

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

Ответ 19

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

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

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    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);
        }
    }

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

    return result;
}

Ответ 20

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

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));

Ответ 21

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.

Ответ 22

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

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

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 in substr(2, 5) чтобы настроить нужную длину.

Ответ 23

Это верно.

<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>

Ответ 24

Создать строку длиной 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;
}

Ответ 25

Как насчет этого компактного маленького трюка?

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var stringLength = 5;

function pickRandom() {
    return possible[Math.floor(Math.random() * possible.length)];
}

var randomString = Array.apply(null, Array(stringLength)).map(pickRandom).join('');

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

Если вы кодируете ES2015, то создание массива немного проще:

var randomString = Array.from({ length: stringLength }, pickRandom).join('');

Ответ 26

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

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

Существуют другие заполнители, такие как A для прописных букв или 9 для цифр.

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

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

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

Ответ 27

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

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

Итак, я буду перефразировать неизменную потребность, поскольку вам нужно некоторое количество строк с небольшим риском повторения. В качестве конкретного примера предположим, что вы хотите создать потенциал в 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"

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

Ответ 28

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

Ответ 29

Вот тест script для ответа # 1 (спасибо @csharptest.net)

script запускает makeid() 1 million раз, и, как вы видите, 5 не является уникальным. запуск его с длиной char 10 достаточно надежный. Я запускал его примерно 50 раз и еще не видел дубликата :-)

Примечание: ограничение размера стека node превышает около 4 миллионов, поэтому вы не можете запустить это 5 миллионов раз, когда он никогда не закончится.

function makeid()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

ids ={}
count = 0
for (var i = 0; i < 1000000; i++) {
    tempId = makeid();
    if (typeof ids[tempId] !== 'undefined') {
        ids[tempId]++;
        if (ids[tempId] === 2) {
            count ++;
        }
        count++;
    }else{
        ids[tempId] = 1;
    }
}
console.log("there are "+count+ ' duplicate ids');

Ответ 30

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

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));