Створення випадкових рядків / символів у JavaScript


1779

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

Який найкращий спосіб зробити це за допомогою JavaScript?


48
Попередження: жодна з відповідей не має true-randomрезультату! Вони є лише pseudo-random. Використовуючи випадкові рядки для захисту чи безпеки, не використовуйте жодну з них !!! Спробуйте один із таких api: random.org
Рон ван дер Хайден

48
Math.random (). ToString (36) .замінити (/ [^ az] + / g, '')
Muaz Khan

13
Будь ласка, покладіть рішення в розчин.
chryss

216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Фрідріх

12
Зауважте, що HTML5 веб-крипто випадковості API забезпечує реальну випадковість.
mikemaccana

Відповіді:


2430

Я думаю, це допоможе вам:

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


117
Це добре для коротких рядків, але будьте обережні, якщо використання +=таких струн призводить до поведінки O (n ^ 2). Якщо ви хочете створити довші рядки, вам слід створити масив окремих символів та об'єднати їх у кінці.
dan_waterworth

97
@dan_waterworth Це , ймовірно , не має значення в майже будь-якому випадку: codinghorror.com/blog/2009/01 / ...
Alex Reece

7
@dan_waterworth, Насправді, +=часто чомусь швидше, навіть використовується всередині циклів - jsperf.com/join-vs-concatenation
Konrad Borowski,

18
@JonathanPaulson Покажіть мені цифри . Дивіться попередній коментар за посиланням jsperf або jsperf.com/sad-tragedy-of-microoptimization або sitepen.com/blog/2008/05/09/string-performance-an-analysis тощо. Також це питання стосується лише 5 конкатенацій .
Алекс Рис

11
@codenamejames Будь ласка , не використовуйте це під час засолювання пароля. Це лише псевдовипадковий не безпечний. Якщо припустити, що ви використовуєте Node (я навіть не впевнений, з чого почати, якщо ви солите на стороні клієнта), використовуйте cryptoзамість цього.
Гідротермальна

2330

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 ... призведе до порожнього або короткого рядка.
Гертас

67
@gertas Цього можна уникнути(Math.random() + 1).toString(36).substring(7);
Джордж Рейт

84
Хлопець, це практично марно. Запустіть його лише 1000000 разів, і ви зазвичай отримаєте близько 110000 повторень: var значень = {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (значення [val]) {duplicateCount ++; } значення [val] = 1; i ++; } 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, я не кажу, що я винайшов рішення, але вже кілька років використовую його у своїх проектах. І це не має нічого спільного з коментарем, який ви згадали. І я цілком впевнений, що в ТА важлива найкорисніша інформація в потрібному місці, і навіть якщо вона вже є в якомусь іншому місці. На щастя, здається, що принаймні 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('');

Редагувати:

Мені здається, що квабіт і Мартійн де Мільяно придумали подібні до останніх рішення (кудо!), Які я якось пропустив. Оскільки вони з першого погляду не виглядають такими короткими, я все одно залишлю його на випадок, якщо хтось дійсно хоче однолінійку :-)

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


Чому б просто не додати 1? (Math.random()+1).toString(36).substring(7);
емікс

Тому що додавання 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 випадкових знаків.)
Едвард Ньюелл

127

Найбільш компактне рішення, тому що 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');

Варіант прикладу можна знайти тут: mediacollege.com/internet/javascript/number/random.html
Девід

1
може також просто декремент lenбезпосередньо в whileциклі
drzaus

Дякую, я щойно опублікував нижче варіант кофескрипту цього прикладу: stackoverflow.com/a/26682781/262379
Дініс Крус

Якщо вони будуть використовуватися публічно, то, ймовірно, слід видалити голосні. Трохи менше ентропії, але набагато безпечніше, оскільки ви не можете створити жодних слів, які можуть образити людей. Ось чому мені це подобається, оскільки я можу надсилати власний рядок символів. Хороша робота.
Нейт Банні

Досить хардкор, працював для мене, Дякую!
Закі Мухаммед

73

Більш нова версія з оператором розповсюдження es6 :

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

  • 30Довільне число, ви можете вибрати будь-який маркер довжину ви хочете
  • 36Максимальне число радікс ви можете перейти до numeric.toString () , що означає все номера і азимуту малі літери
  • 2Використовуються , щоб вибрати 3 - ї індекс від випадкової рядки , яка виглядає наступним чином : "0.mfbiohx64i"ми могли б взяти будь-який індекс після0.

Чи можете ви пояснити? Особливо, чому ви передаєте 36 в toString () і чому ви обираєте 3-й елемент?
вуза

5
це найкраще рішення
подоланий

приємно, але це рішення не містить символів [AZ] як запитане запитання, лише [a-z0-9]
Nahuel Greco

71

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


Мені це подобається найкраще. Ви можете легко змінити, щоб прийняти додаткові параметри і повернути лише числа, пониження або обмеження. Я не думаю, що ультракомпресований стиль необхіднийwhile(s.length< L) s+= randomchar();
mastaBlasta

3
Також while(L--)зроблять це
vsync

1
Краще використовувати більш надійне, 'A'.charCodeAt(0)а не магічне число 55(і так само 61). Тим більше, що на моїй платформі все-таки є магічне число, яке повертається 65. Цей код також буде самостійно документувати.
Grumdrig

Я створив мініфікацію оптимізовану (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 , давайте розбимо його на основні (лише для Alpha-Numeric) для кращого розуміння:

  • Створіть функцію, яка приймає аргумент (потрібна довжина випадкового результату String)
  • Створіть порожній рядок, як var str = "";об'єднати випадкові символи
  • Всередині циклу створіть randчисло індексу від 0 до 61 (0..9 + A..Z + a..z = 62)
  • Створіть умовну логіку для налаштування / виправленняrand (оскільки це 0..61), збільшивши її на деяку кількість (див. Приклади нижче), щоб повернути потрібне CharCodeчисло та відповідний символ.
  • Всередині петля з'єднується в straString.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) уявлення про нього.


Я не зовсім впевнений, як це відповідає на питання; Це 7-річне запитання, в якому вже багато вагомих відповідей. Якщо ви вирішите надати нову відповідь, вам слід бути особливо обережним, щоб переконатися, що ваша відповідь добре пояснена та задокументована.
Claies

1
Якщо ви використовуєте Date, чому ви просто не використовуєте його так:(+new Date).toString(36)
seniorpreacher

Мені подобається ваше рішення з випадковими числами, але 9e6 дає лише 9 мільйонів можливостей за 60,4 мільйона для 5 цифр (36 ^ 5), щоб ви могли замінити його, (0|Math.random()*6.04e7).toString(36)щоб охопити його.
Le Droid

1
Я хотів довгу випадкову рядок з короткою можливою процедурою (для демонстрації коду), яка не повинна бути криптографічно дивовижною, просто створити якийсь хороший випадковий візуальний "пух". Мені подобається ця відповідь найкраща (Ваша 2-а), тому дякую. Мої два цента: я можу побити його для стислості одним натисканням клавіші менше, і це, як правило , виробляють 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"]();});

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 = '');
Thomas Heymann

Спроба мікрооптимізації під час використання "приємного", але рекурсивного алгоритму витрачання ресурсів не має сенсу :-) А цикл все ще найкращий у Javascript та б'є рекурсію великим часом, поки не будуть досягнуті дійсно великі досягнення в оптимізаційному коді виконання.
Мерре

17

Якщо ви використовуєте Lodash або Underscore , то це так просто:

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

6
Лодаш використовує_.sampleSize('asdfgh',5).join('')
marlo

2
Це насправді не є вдалим рішенням, оскільки кожен документ складається з унікального індексу. Це означає, що це не справді випадково, оскільки жоден персонаж не може / ніколи не повториться.
random_user_name

16

Для задоволення вимоги [a-zA-Z0-9] та довжини = 5 використовуйте

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

З'являться малі літери, великі літери та цифри.


1
Я думаю, що Math.random () може призвести до базового64-рядка з занадто мало символів.
Лейф

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 - це «
однолінійний

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

Якщо припустити, що ви підкреслили, ви можете елегантно генерувати випадкову рядок всього в двох рядках:

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

6
Це зробить повернене значення всім унікальним символом. Також довжина струни обмежена до можливої ​​довжини var.
Yefu


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 .


Для мене це завжди генерує випадкові рядки з 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));


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)пристосуватися до довжини вам.


6

Один вкладиш:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil

Щоб скоротити аргумент зміни Array(15)на менше значення. Наприклад: Array(4).
Андрій

Я дуже люблю це рішення, просте і зрозуміле. Він генерує 15 випадкових чисел між 0 і 1, генерує шістнадцятковий, а потім видаляє перші два символи. Нарешті, це єднання їх усіх разом.
Siscia

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) не дуже випадковий, але короткий і досить унікальний кожен раз, коли ви його називаєте.


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

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

4

Можна використовувати кодерин . Це бібліотека для генерування випадкових кодів за заданою схемою. Використовуйте #як заповнювач для великих і малих символів, а також цифр:

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

Є й інші заповнювачі, такі як Aвеликі літери або9 для цифр.

Що може бути корисним - це дзвінок .next() завжди дадуть вам унікальний результат, тому вам не доведеться турбуватися про дублікати.

Ось демонстраційний додаток, який генерує список унікальних випадкових кодів .

Повне розкриття: Я автор кодерена.


НІ НІ НЕ - використовуйте нативні методи.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.