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


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

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


1117


источник


Ответы:


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

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

console.log(makeid());


1587



Math.random().toString(36).substring(7);

1693



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

Опция 1

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

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

// "bb5dc8842ca31d4603d6aa11448d1654"

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


Вариант 2

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

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

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

Вариант 3

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

// dec2hex :: Integer -> String
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"


223



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

Во-первых, как отмечали другие, он имеет небольшую вероятность создания коротких строк или даже пустой строки (если случайное число равно 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. Преобразуйте число в строку базы 36, то есть используя символы 0-9 и a-z.
  3. Пэд с нулями (решает первый выпуск).
  4. Отрежьте ведущий «0». префикс и дополнительные прописные нули.
  5. Повторите строку достаточно времени, чтобы иметь в ней по крайней мере N символов (путем объединения пустых строк с более короткой случайной строкой, используемой в качестве разделителя).
  6. Нарежьте ровно N символов из строки.

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

  • Это решение не использует прописные буквы, но почти во всех случаях (без каламбура) это не имеет значения.
  • Максимальная длина строки при N = 16 в исходном ответе измеряется в Chrome. В Firefox это N = 11. Но, как объяснено, второе решение касается поддержки любой требуемой длины строки, а не добавления случайности, поэтому это не имеет большого значения.
  • Все возвращенные строки имеют равную вероятность возврата, по крайней мере, до тех пор, пока результаты, возвращаемые Math.random (), не будут распределены равномерно (это не случайная криптографическая сила, в любом случае).
  • Не все возможные строки размера N могут быть возвращены. Во втором решении это очевидно (так как меньшая строка просто дублируется), но также и в исходном ответе, это верно, так как при преобразовании на базу-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 а также Мартиан де Мильяно придумали решения, подобные последним (kudos!), которые я как-то пропустил. Поскольку они не выглядят краткими, я останусь здесь все равно, если кто-то действительно хочет однострочный :-)

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


127



Короткие, легкие и надежные

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

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

121



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

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

81



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


61



The most compact solution, because slice is shorter than substring. Subtracting from the end of the string allows to avoid floating point symbol generated by random function:

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

or even

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

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

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


46



Random String Generator (Alpha-Numeric | Alpha | Numeric)

/**
 * 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"

Have fun. jsBin demo


While the above uses additional checks for the desired (A/N, A, N) output, let's break it down the to the essentials (Alpha-Numeric only) for a better understanding:

  • Create a function that accepts an argument (desired length of the random String result)
  • Create an empty string like var str = ""; to concatenate random characters
  • Inside a loop create a rand index number from 0 to 61 (0..9+A..Z+a..z = 62)
  • Create a conditional logic to Adjust/fix rand (since it's 0..61) incrementing it by some number (see examples below) to get back the right CharCode number and the related Character.
  • Inside the loop concatenate to str a String.fromCharCode( incremented rand )

Let's picture the Character table and their ranges:

_____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 ) gives a range from 0..61 (what we need). How to fix (increment) the random to get the correct charCode ranges?

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

The conditional operation logic from the table above:

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

If you followed the above explanation you should be able to create this alpha-numeric snippet:

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"

Or if you will:

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

39