Мне нужна строка из 5 символов, состоящая из символов, выбранных случайным образом из набора [a-zA-Z0-9]
.
Какой лучший способ сделать это с помощью JavaScript?
Думаю, это сработает для вас:
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());
+=
для таких строк приводит к тому, что он будет иметь поведение O (n ^ 2). Если вы хотите создать более длинные строки, вы должны создать массив отдельных символов и соединить их вместе в конце.
let r = Math.random().toString(36).substring(7);
console.log("random", r);
Примечание: приведенный выше алгоритм имеет следующие недостатки:
Math.random()
может выдавать предсказуемый ("случайный", но не случайный) результат в зависимости от реализации. Результирующая строка не подходит, когда вам нужно гарантировать уникальность или непредсказуемость.Math.random().toString(36).substr(2, 5)
, потому что .substring(7)
делает его длиннее 5 символов. Полный балл, все же!
Math.random плохо для такого рода вещей
Вариант 1
Если вы можете сделать это на стороне сервера, просто используйте crypto module
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
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"
Возвращает ровно 5 случайных символов, в отличие от некоторых самых популярных ответов, найденных здесь.
Math.random().toString(36).substr(2, 5);
Math.random().toString(36)
возвращает число длиной менее 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)
Пояснение:
Дальнейшие мысли:
Update:
Вот пара других функциональных стилей с одним слоем, которые я придумал. Они отличаются от решения выше тем, что:
Итак, скажем, ваш алфавит выбора
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" во всех решениях, чтобы слить еще несколько байтов.
(Math.random()+1).toString(36).substring(7);
Что-то вроде этого должно работать
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');
len
непосредственно в while
петли
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();
стиль необходим, while(s.length< L) s+= randomchar();
Наиболее компактное решение, потому что slice
короче substring
. Вычитание из конца строки позволяет избежать символа с плавающей запятой, сгенерированного random
функцией:
Math.random().toString(36).slice(-5);
или даже
(+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));
/**
* 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) для лучшего понимания:
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 ;
Если вы следуете приведенному выше объяснению, вы сможете создать этот альфа-цифровой фрагмент:
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;
}
Более новая версия с оператором распространения es6:
[...Array(30)].map(() => Math.random().toString(36)[3]).join('')
30
- произвольное число, вы можете выбрать любую желаемую длину токена.36
- это максимальное число радиуса, которое вы можете передать numeric.toString(), что означает все цифры и строчные буквы az3
используется для выбора третьего числа из случайной строки, которая выглядит следующим образом: "0.mfbiohx64i"
, мы можем взять любой индекс после 0.
Самый простой способ:
(new Date%9e6).toString(36)
Это генерирует случайные строки из 5 символов в зависимости от текущего времени. Пример вывода: 4mtxj
или 4mv90
или 4mwp1
Проблема заключается в том, что если вы вызовете это два раза за ту же секунду, она будет генерировать ту же строку.
Более безопасный способ:
(0|Math.random()*9e6).toString(36)
Это создаст случайную строку из 4 или 5 символов, всегда отличающуюся. Пример вывода похож на 30jzm
или 1r591
или 4su1a
В обоих случаях первая часть генерирует случайное число. Часть .toString(36)
передала число в базовое36 (буквенно-цифровое) представление.
(+new Date).toString(36)
Вот несколько простых лайнеров. Измените 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"]();});
Если вы используете Lodash или Underscore, то это так просто:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
_.sampleSize('asdfgh',5).join('')
Я знаю, что у всех все получилось правильно, но я чувствовал себя как можно лучше в этом легком (светлый код, а не процессор):
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.
current = current ? current : '';
когда вы можете написать current = current || ''
;
current || (current = '');
Вот метод, который я создал.
Это создаст строку, содержащую как прописные, так и строчные буквы.
Кроме того, я включил функцию, которая будет также создавать буквенно-цифровую строку.
Рабочие примеры:
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)));
}
Предполагая, что вы используете underscorejs, можно элегантно генерировать случайную строку только в двух строках:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
Для удовлетворения требования [a-zA-Z0-9] и длины = 5 используйте
btoa(Math.random()).substr(5, 5);
Будут встречаться строчные буквы, прописные буквы и цифры.
Если кто-то интересуется однострочным (хотя и не отформатированным как таковое для вашего удобства), который выделяет память сразу (но обратите внимание, что для небольших строк это действительно не имеет значения) вот как это сделать:
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)
.
Быстрый и улучшенный алгоритм. Не гарантирует единообразность (см. Комментарии).
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;
}
crypto.getRandomValues
возвращает одно из 256 уникальных значений. Поскольку 256 не делится на 62, вероятность того, что персонажи получат AH, несколько выше. Я думаю, что лучшим решением будет сделать то, что сделал YouTube, и просто добавить 2 дополнительных символа (возможно -
и _
) в кодировку. Во всяком случае, отличная работа - этот ответ требует гораздо больше любви :)
Вы можете прокручивать массив элементов и рекурсивно добавлять их к строковой переменной, например, если вы хотите случайную последовательность ДНК:
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));
Я не нашел чистого решения для поддержки как строчных, так и прописных букв.
Поддержка только в нижнем регистре:
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)
чтобы настроить нужную длину.
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
: - /
--strLength
на strLength--
исправляет это для меня.
Как насчет чего-то вроде этого: Date.now().toString(36)
Не очень случайный, но короткий и совершенно уникальный каждый раз, когда вы его называете.
Date.now()
имеет разрешение только в миллисекундах. Например, при запуске в простом цикле вы получите много дубликатов. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }
Проблема с ответами на вопросы "Мне нужны случайные строки" (на любом языке) практически в каждом решении используется некорректная первичная спецификация длины строки. Сами вопросы редко показывают, почему нужны случайные строки, но я бы бросил вызов вам редко нужны случайные строки длины, скажем 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"
Обратите внимание на разницу в длине строки из-за разницы в общем количестве символов в используемом наборе символов. Риск повторения в указанном числе потенциальных строк одинаковый. Длина строк не является. И, самое главное, риск повторения и потенциального количества строк является явным. Больше не догадывается длина строки.
Вы можете использовать coderain. Это библиотека для генерации случайных кодов в соответствии с заданным шаблоном. Используйте #
в качестве заполнителя для символов верхнего и нижнего регистра, а также цифр:
var cr = new CodeRain("#####");
console.log(cr.next());
Существуют другие заполнители, такие как A
для прописных букв или 9
для цифр.
Что может быть полезно, так это то, что вызов .next()
всегда даст вам уникальный результат, поэтому вам не придется беспокоиться о дубликатах.
Вот демонстрационное приложение, которое создает список уникальных случайных кодов.
Полное раскрытие: я автор кодераина.
Создать строку длиной 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;
}
Это верно.
<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>
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
как в принятом ответе, поэтому результат функции более настраиваемый.
Вот тест 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');
Как насчет этого компактного маленького трюка?
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('');
Этот сочетает в себе многие ответы дают.
var randNo = Math.floor(Math.random() * 100) + 2 + "" + new Date().getTime() + Math.floor(Math.random() * 100) + 2 + (Math.random().toString(36).replace(/[^a-zA-Z]+/g, '').substr(0, 5));
console.log(randNo);
Я использую его в течение 1 месяца с отличными результатами.
Если библиотека является возможностью, Chance.js может помочь: http://chancejs.com/#string
Это то, что я использовал. Сочетание пары здесь. Я использую его в цикле, и каждый идентификатор, который он производит, уникален. Это может быть не 5 символов, но это гарантирует уникальность.
var newId =
"randomid_" +
(Math.random() / +new Date()).toString(36).replace(/[^a-z]+/g, '');
Развернувшись на элегантном примере Doubletap, отвечая на вопросы, поднятые Гертасом и Драконом. Просто добавьте цикл while для проверки тех редких нулевых обстоятельств и ограничьте символы до пяти.
function rndStr() {
x=Math.random().toString(36).substring(7).substr(0,5);
while (x.length!=5){
x=Math.random().toString(36).substring(7).substr(0,5);
}
return x;
}
Здесь jsfiddle предупреждает вас о результате: http://jsfiddle.net/pLJJ7/
Это слегка улучшенная версия ответа двойного касания. Он рассматривает gertas комментарий о случае, когда Math.random()
возвращает 0, 0.5, 0.25, 0.125 и т.д.
((Math.random()+3*Number.MIN_VALUE)/Math.PI).toString(36).slice(-5)
toString
добавляя наименьшее число с плавающей точкой в Math.random()
.toString
имеет достаточное количество цифр путем деления на почти иррациональное число.Для строки с upper- и строчными буквами и цифрами (0-9a-zA-Z) это может быть версия, которая минимизирует лучше всего:
function makeId(length) {
var id = '';
var rdm62;
while (length--) {
// Generate random integer between 0 and 61, 0|x works for Math.floor(x) in this case
rdm62 = 0 | Math.random() * 62;
// Map to ascii codes: 0-9 to 48-57 (0-9), 10-35 to 65-90 (A-Z), 36-61 to 97-122 (a-z)
id += String.fromCharCode(rdm62 + (rdm62 < 10 ? 48 : rdm62 < 36 ? 55 : 61))
}
return id;
}
Содержимое этой функции уменьшается до 97 байт, а верхнему ответу требуется 149 байт (из-за списка символов).
Этот метод вернет случайную строку с любым из поддерживаемых символов Юникода, что не на 100% соответствует тому, что запрашивает OP, а то, что я искал:
function randomUnicodeString(length){
return Array.from({length: length}, ()=>{
return String.fromCharCode(Math.floor(Math.random() * (65536)))
}).join('')
}
Это лучший результат Google при поиске "случайного строкового JavaScript", но OP запрашивает только a-zA-Z0-9.
Программисты резали бумагу лазерами, а не бензопилами. Использование fringe, специфичных для языка методов для создания наименьшего, наиболее запутанного кода - это мило и все, но никогда не предложит полного решения. Вы должны использовать правильный инструмент для работы.
То, что вы хотите, это строка символов, и символы представлены байтами. И мы можем представить байт в JavaScript, используя число. Итак, мы должны сгенерировать список этих чисел и привести их в виде строк. Вам не нужны дата или base64; Math.random() получит вам число, а String.fromCharCode() превратит его в строку. Легко.
Но какое число равно какому символу? UTF-8 является основным стандартом, используемым в Интернете для интерпретации байтов как символов (хотя JavaScript использует UTF-16 внутри, они перекрываются). Способ решения этой проблемы для программиста - изучить документацию.
UTF-8 перечисляет все клавиши на клавиатуре в числах от 0 до 128. Некоторые из них не для печати. Просто выберите нужные символы в ваших случайных строках и найдите их, используя случайно сгенерированные числа.
Сильфон - это функция, которая принимает практически бесконечную длину, генерирует случайное число в цикле и ищет все печатные символы в младших 128 кодах UTF-8. Энтропия присуща, поскольку не все случайные числа будут попадаться каждый раз (непечатные символы, пробелы и т.д.). Он также будет работать быстрее, если вы добавите больше символов.
Я включил большинство оптимизаций, обсуждаемых в теме:
function randomID(len) {
var char;
var arr = [];
var len = len || 5;
do {
char = ~~(Math.random() * 128);
if ((
(char > 47 && char < 58) || // 0-9
(char > 64 && char < 91) || // A-Z
(char > 96 && char < 123) // a-z
// || (char > 32 && char < 48) // !"#$%&,()*+'-./
// || (char > 59 && char < 65) // <=>?@
// || (char > 90 && char < 97) // [\]^_'
// || (char > 123 && char < 127) // {|}~
)
//security conscious removals: " ' \ '
//&& (char != 34 && char != 39 && char != 92 && char != 96)
) { arr.push(String.fromCharCode(char)) }
} while (arr.length < len);
return arr.join('')
}
var input = document.getElementById('length');
input.onfocus = function() { input.value = ''; }
document.getElementById('button').onclick = function() {
var view = document.getElementById('string');
var is_number = str => ! Number.isNaN( parseInt(str));
if ( is_number(input.value))
view.innerText = randomID(input.value);
else
view.innerText = 'Enter a number';
}
#length {
width: 3em;
color: #484848;
}
#string {
color: #E83838;
font-family: 'sans-serif';
word-wrap: break-word;
}
<input id="length" type="text" value='#'/>
<input id="button" type="button" value="Generate" />
<p id="string"></p>
Почему это так утомительно? Потому что ты можешь. Вы программист. Вы можете заставить компьютер делать что угодно! Кроме того, что, если вам нужна строка символов иврита? Это не сложно. Найдите эти символы в стандарте UTF-8 и найдите их. Освободите себя от таких методов Макдональда, как toString (36).
Иногда опускание до более низкого уровня абстракции - это то, что необходимо для создания реального решения. Понимание основных принципов под рукой может позволить вам настроить свой код так, как вам хочется. Может быть, вы хотите, чтобы бесконечно сгенерированная строка заполняла круговой буфер? Может быть, вы хотите, чтобы все ваши сгенерированные строки были палиндромами? Зачем сдерживать себя?
Math.floor
.
Вот другой подход с фиксированной длиной по базе, без RegExp заменить недостаток (на основе ответа @bendytree);
function rand(base) {
// default base 10
base = (base >= 2 && base <= 36) ? base : 10;
for (var i = 0, ret = []; i < base; i++) {
ret[i] = ((Math.random() * base) | 0).toString(base)
// include 0-9a-zA-Z?
// [Math.random() < .5 ? 'toString' : 'toUpperCase']();
}
return ret.join('');
}
Случайное числовое значение (до 16 цифр)
/**
* Random numeric value (up to 16 digits)
* @returns {String}
*/
function randomUid () {
return String(Math.floor(Math.random() * 9e15))
}
// randomUid() -> "3676724552601324"
Я использую var randId = 'rand' + new Date().getTime();
Функциональный подход. Этот ответ практичен только в том случае, если функциональные предпосылки можно использовать в других частях приложения. Производительность, вероятно, нежелательная, но было супер весело писать.
// functional prerequisites
const U = f=> f (f)
const Y = U (h=> f=> f (x=> h (h) (f) (x)))
const comp = f=> g=> x=> f (g (x))
const foldk = Y (h=> f=> y=> ([x, ...xs])=>
x === undefined ? y : f (y) (x) (y=> h (f) (y) (xs)))
const fold = f=> foldk (y=> x=> k=> k (f (y) (x)))
const map = f=> fold (y=> x=> [...y, f (x)]) ([])
const char = x=> String.fromCharCode(x)
const concat = x=> y=> y.concat(x)
const concatMap = f=> comp (fold (concat) ([])) (map (f))
const irand = x=> Math.floor(Math.random() * x)
const sample = xs=> xs [irand (xs.length)]
// range : make a range from x to y; [x...y]
// Number -> Number -> [Number]
const range = Y (f=> r=> x=> y=>
x > y ? r : f ([...r, x]) (x+1) (y)
) ([])
// srand : make random string from list or ascii code ranges
// [(Range a)] -> Number -> [a]
const srand = comp (Y (f=> z=> rs=> x=>
x === 0 ? z : f (z + sample (rs)) (rs) (x-1)
) ([])) (concatMap (map (char)))
// idGenerator : make an identifier of specified length
// Number -> String
const idGenerator = srand ([
range (48) (57), // include 0-9
range (65) (90), // include A-Z
range (97) (122) // include a-z
])
console.log (idGenerator (6)) //=> TT688X
console.log (idGenerator (10)) //=> SzaaUBlpI1
console.log (idGenerator (20)) //=> eYAaWhsfvLDhIBID1xRh
По моему мнению, трудно превзойти ясность idGenerator
, не добавляя магические, слишком-много-важные функции.
Небольшое улучшение может быть
// ord : convert char to ascii code
// Char -> Number
const ord = x => x.charCodeAt(0)
// idGenerator : make an identifier of specified length
// Number -> String
const idGenerator = srand ([
range (ord('0')) (ord('9')),
range (ord('A')) (ord('Z')),
range (ord('a')) (ord('z'))
])
Получайте удовольствие от этого. Позвольте мне узнать, что вам нравится/узнать ^ _ ^
fold
от foldk
: D
Мне понравилась краткость doubletap Math.random(). toString (36).substring(7) отвечают, но не так, что у нее было так много конфликтов, как хакликекарт правильно указал. Он генерировал строки с 11 символами, но имел повторяющуюся скорость 11% при размере выборки в 1 миллион.
Здесь длинная (но еще короткая) и более медленная альтернатива, в которой было всего 133 дубликата в выборке размером 1 миллион. В редких случаях строка будет меньше 11 символов:
Math.abs(Math.random().toString().split('')
.reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11);
Здесь хранится 5 буквенно-цифровых символов в переменной c.
for(var c = ''; c.length < 5;) c += Math.random().toString(36).substr(2, 1)
",,,,,".replace(/,/g,function (){return "AzByC0xDwEv9FuGt8HsIrJ7qKpLo6MnNmO5lPkQj4RiShT3gUfVe2WdXcY1bZa".charAt(Math.floor(Math.random()*62))});
Также, основываясь на ответе doubletap, он обрабатывает любую длину случайных символов (только ниже) и продолжает генерировать случайные числа до тех пор, пока не будет собрано достаточно символов.
function randomChars(len) {
var chars = '';
while (chars.length < len) {
chars += Math.random().toString(36).substring(2);
}
// Remove unnecessary additional characters.
return chars.substring(0, len);
}
"12345".split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');
//or
String.prototype.rand = function() {return this.split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');};
будет генерировать случайную буквенно-цифровую строку с длиной первой/вызывающей строки
Как об этом ниже... это даст действительно случайные значения:
function getRandomStrings(length) {
const value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const randoms = [];
for(let i=0; i < length; i++) {
randoms.push(value[Math.floor(Math.random()*value.length)]);
}
return randoms.join('');
}
Но если вы ищете более короткий синтаксис в ES6:
const getRandomStrings = length => Math.random().toString(36).substr(-length);
Как указали несколько человек, передача результата Math.random()
напрямую в .string(36)
имеет несколько проблем.
У него плохая случайность. Количество сгенерированных символов варьируется, и в среднем зависит от хитрых деталей работы чисел с плавающей запятой в Javascript. Кажется, это работает, если я пытаюсь сгенерировать 11 символов или менее, но не с более чем 11. И это не гибкий. Нет простого способа разрешить или запретить определенные символы.
У меня есть компактное решение, которое не имеет этих проблем, для тех, кто использует lodash:
_.range(11).map(i => _.sample("abcdefghijklmnopqrstuvwxyz0123456789")).join('')
Если вы хотите разрешить определенные символы (например, заглавные буквы) или запретить определенные символы (например, неоднозначные символы, такие как l
и 1
), измените приведенную выше строку.
рекурсивное решение:
function generateRamdomId (seedStr) {
const len = seedStr.length
console.log('possibleStr', seedStr , ' len ', len)
if(len <= 1){
return seedStr
}
const randomValidIndex = Math.floor(Math.random() * len)
const randomChar = seedStr[randomValidIndex]
const chunk1 = seedStr.slice(0, randomValidIndex)
const chunk2 = seedStr.slice(randomValidIndex +1)
const possibleStrWithoutRandomChar = chunk1.concat(chunk2)
return randomChar + generateRamdomId(possibleStrWithoutRandomChar)
}
Вы можете использовать с семенем, которое вы хотите, не повторяйте символы, если вы не читаете. пример
generateRandomId("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
Вы можете использовать base64:
function randomString(length)
{
var rtn = "";
do {
rtn += btoa("" + Math.floor(Math.random() * 100000)).substring(0, length);
}
while(rtn.length < length);
return rtn;
}
Я сделал прототип String, который может генерировать случайные строки заданной длины.
Вы также можете закрепиться, если вы хотите специальные символы и вы можете избежать некоторых.
/**
* STRING PROTOTYPE RANDOM GENERATOR
* Used to generate a random string
* @param {Boolean} specialChars
* @param {Number} length
* @param {String} avoidChars
*/
String.prototype.randomGenerator = function (specialChars = false, length = 1, avoidChars = '') {
let _pattern = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
_pattern += specialChars === true ? '(){}[]+-*/=' : '';
if (avoidChars && avoidChars.length) {
for (let char of avoidChars) {
_pattern = _pattern.replace(char, '');
}
}
let _random = '';
for (let element of new Array(parseInt(length))) {
_random += _pattern.charAt(Math.floor(Math.random() * _pattern.length));
}
return _random;
};
Вы можете использовать как это:
// Generate password with specialChars which contains 10 chars and avoid iIlL chars
var password = String().randomGenerator(true, 10, 'iIlL');
Надеюсь, поможет.
очень просто
function getRandomColor(){
var color='';
while(color.length<6){
color=Math.floor(Math.random()*16777215).toString(16);
}
return '#'+color;
}
Попробуйте, что я использую каждый раз:
function myFunction() {
var hash = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789";
var random8 = '';
for(var i = 0; i < 5; i++){
random8 += hash[parseInt(Math.random()*hash.length)];
}
console.log(random8);
document.getElementById("demo").innerHTML = "Your 5 character string ===> "+random8;
}
<!DOCTYPE html>
<html>
<body>
<p>Click the button to genarate 5 character random string .</p>
<button onclick="myFunction()">Click me</button>
<p id="demo"></p>
</body>
</html>
в следующем коде я генерирую случайный код для 8 символов
function RandomUnique(){
var charBank = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789";
var random= '';
var howmanycharacters = 8;
for (var i = 0; i < howmanycharacters ; i++) {
random+= charBank[parseInt(Math.random() * charBank.lenght)];
}
return random;
}
var random = RandomUnique();
console.log(random);
Модуль npm anyid предоставляет гибкий API для генерации различных типов ID/кода строки.
const id = anyid().encode('Aa0').length(5).random().id();
Поместите символы как thisArg
в функцию карты, создайте "однострочный":
Array.apply(null, Array(5))
.map(function(){
return this[Math.floor(Math.random()*this.length)];
}, "abcdefghijklmnopqrstuvwxyz")
.join('');
Это для хром-кода firefox (аддоны и т.п.)
Это может сэкономить вам несколько часов исследований.
function randomBytes( amount )
{
let bytes = Cc[ '@mozilla.org/security/random-generator;1' ]
.getService ( Ci.nsIRandomGenerator )
.generateRandomBytes( amount, '' )
return bytes.reduce( bytes2Number )
function bytes2Number( previousValue, currentValue, index, array )
{
return Math.pow( 256, index ) * currentValue + previousValue
}
}
Используйте его как:
let strlen = 5
, radix = 36
, filename = randomBytes( strlen ).toString( radix ).splice( - strlen )
Еще один хороший способ рандомизировать строку из символов A-Za-z0-9
:
function randomString(length) {
if ( length <= 0 ) return "";
var getChunk = function(){
var i, //index iterator
rand = Math.random()*10e16, //execute random once
bin = rand.toString(2).substr(2,10), //random binary sequence
lcase = (rand.toString(36)+"0000000000").substr(0,10), //lower case random string
ucase = lcase.toUpperCase(), //upper case random string
a = [lcase,ucase], //position them in an array in index 0 and 1
str = ""; //the chunk string
b = rand.toString(2).substr(2,10);
for ( i=0; i<10; i++ )
str += a[bin[i]][i]; //gets the next character, depends on the bit in the same position as the character - that way it will decide what case to put next
return str;
},
str = ""; //the result string
while ( str.length < length )
str += getChunk();
str = str.substr(0,length);
return str;
}
Вот пример в CoffeeScript:
String::add_Random_Letters = (size )->
charSet = 'abcdefghijklmnopqrstuvwxyz'
@ + (charSet[Math.floor(Math.random() * charSet.length)] for i in [1..size]).join('')
который можно использовать
value = "abc_"
value_with_exta_5_random_letters = value.add_Random_Letters(5)
Здесь версия Coffeescript одна строка кода
genRandomString = (length,set) -> [0...length].map( -> set.charAt Math.floor(Math.random() * set.length)).join('')
Использование:
genRandomString 5, 'ABCDEFTGHIJKLMNOPQRSTUVWXYZ'
Вывод:
'FHOOV' # random string of length 5 in possible set A~Z
true-random
результата! Они толькоpseudo-random
. При использовании случайных строк для защиты или безопасности не используйте ни одну из них !!! Попробуйте один из этих API: random.org