Genereer willekeurige tekenreeksen/tekens in JavaScript

Ik wil een reeks van 5 tekens die is samengesteld uit willekeurig gekozen tekens uit de set [a-zA-Z0-9].

Wat is de beste manier om dit te doen met JavaScript?


Antwoord 1, autoriteit 100%

Ik denk dat dit voor jou zal werken:

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

Antwoord 2, autoriteit 90%

//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);

Antwoord 3, autoriteit 22%

Math.randomis slecht voor dit soort dingen

Optie 1

Als je deze server-kant kunt doen, gebruik dan gewoon de crypto-module –

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

De resulterende string zal twee keer zo lang zijn als de willekeurige bytes die je genereert; elke byte gecodeerd naar hex is 2 tekens. 20 bytes zijn 40 tekens van hex.


Optie 2

Als je deze client-kant moet doen, probeer dan misschien de uuid-module –

var uuid = require("uuid");
var id = uuid.v4();
// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

Optie 3

Als u deze client-kant moet doen en u hoeft geen oude browsers te ondersteunen, dan kunt u dit doen zonder afhankelijkheden –

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
  return dec.toString(16).padStart(2, "0")
}
// 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"

Antwoord 4, autoriteit 7%

Kort, gemakkelijk en betrouwbaar

Retourneert precies 5 willekeurige tekens, in tegenstelling tot enkele van de best beoordeelde antwoorden die hier te vinden zijn.

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

Antwoord 5, autoriteit 6%

Hier is een verbetering ten opzichte van het uitstekende antwoord van Doubletap. Het origineel heeft twee nadelen die hier worden behandeld:

Ten eerste, zoals anderen al hebben gezegd, heeft het een kleine kans om korte strings of zelfs een lege string te produceren (als het willekeurige getal 0 is), wat je applicatie kan breken. Hier is een oplossing:

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

Ten tweede beperken zowel het origineel als de bovenstaande oplossing de tekenreeksgrootte N tot 16 tekens. Het volgende geeft een tekenreeks met de grootte N terug voor elke N (maar merk op dat het gebruik van N > 16 de willekeur niet zal vergroten of de kans op botsingen zal verkleinen):

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

Uitleg:

  1. Kies een willekeurig getal in het bereik [0,1), d.w.z. tussen 0 (inclusief) en 1 (exclusief).
  2. Converteer het getal naar een tekenreeks met grondtal 36, d.w.z. met de tekens 0-9 en a-z.
  3. Pad met nullen (lost het eerste probleem op).
  4. Snijd de leidende ‘0’ af.’ prefix en extra opvulnullen.
  5. Herhaal de tekenreeks zo vaak dat er ten minste N tekens in staan (door lege tekenreeksen samen te voegen met de kortere willekeurige tekenreeks die als scheidingsteken wordt gebruikt).
  6. Snijd precies N tekens uit de tekenreeks.

Verdere gedachten:

  • Deze oplossing gebruikt geen hoofdletters, maar in bijna alle gevallen (geen woordspeling bedoeld) maakt het niet uit.
  • De maximale tekenreekslengte bij N = 16 in het oorspronkelijke antwoord wordt gemeten in Chrome. In Firefox is dit N = 11. Maar zoals uitgelegd, gaat de tweede oplossing over het ondersteunen van elke gewenste stringlengte, niet over het toevoegen van willekeur, dus het maakt niet veel uit.
  • Alle geretourneerde strings hebben een gelijke kans om te worden geretourneerd, tenminste voor zover de resultaten die worden geretourneerd door Math.random() gelijkmatig zijn verdeeld (dit is in ieder geval geen willekeur met cryptografie-sterkte).
  • Niet alle mogelijke tekenreeksen met de grootte N mogen worden geretourneerd. In de tweede oplossing is dit duidelijk (omdat de kleinere string gewoon wordt gedupliceerd), maar ook in het oorspronkelijke antwoord is dit waar, omdat bij de conversie naar basis-36 de laatste paar bits mogelijk geen deel uitmaken van de oorspronkelijke willekeurige bits. In het bijzonder, als je kijkt naar het resultaat van Math.random().toString(36), zul je merken dat het laatste teken niet gelijkmatig is verdeeld. Nogmaals, in bijna alle gevallen maakt het niet uit, maar we snijden de laatste string vanaf het begin in plaats van het einde van de willekeurige string, zodat korte strings (bijv. N=1) niet worden beïnvloed.

Bijwerken:

Hier zijn een paar andere functionele oneliners die ik heb bedacht. Ze verschillen van de bovenstaande oplossing doordat:

  • Ze gebruiken een expliciet willekeurig alfabet (meer generiek en geschikt voor de oorspronkelijke vraag die zowel om hoofdletters als kleine letters vroeg).
  • Alle strings met lengte N hebben een gelijke kans om te worden geretourneerd (d.w.z. strings bevatten geen herhalingen).
  • Ze zijn gebaseerd op een kaartfunctie, in plaats van de toString(36)-truc, waardoor ze eenvoudiger en gemakkelijker te begrijpen zijn.

Dus, stel dat je alfabet naar keuze is

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Deze twee zijn gelijk aan elkaar, dus je kunt kiezen wat voor jou het meest intuïtief is:

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

en

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

Bewerken:

Ik lijkt op qubyteen Martijn de Millianokwam met soortgelijke oplossingen (kudos!), die ik op de een of andere manier miste. Omdat ze er op het oog niet zo kort uitzien, laat ik het hier toch bij voor het geval iemand echt een oneliner wil 🙂

Ook in alle oplossingen ‘new Array’ vervangen door ‘Array’ om nog een paar bytes te besparen.


Antwoord 6, autoriteit 5%

De meest compacte oplossing, omdat sliceis korter dan substring. Door af te trekken van het einde van de tekenreeks kunt u het drijvende-kommasymbool vermijden dat wordt gegenereerd door de randomfunctie:

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

of zelfs

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

UPDATE: Nog een meer benadering toegevoegd met btoamethode:

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

Antwoord 7, Autoriteit 4%

Een nieuwere versie met ES6 Spread-operator :

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

  • De 30is een willekeurig nummer, u kunt elke gewenste tokenlengte kiezen
  • De 36is het maximale Radix-nummer dat u kunt gaan naar numerieke.tostring () , wat betekent alle nummers en AZ kleine letters
  • De 2wordt gebruikt om de 3e index te kiezen uit de willekeurige tekenreeks die er als volgt uitziet: "0.mfbiohx64i", we kunnen elke index nemen na 0.

Antwoord 8, autoriteit 4%

Zoiets zou moeten werken

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

Bel met standaardtekenset [a-zA-Z0-9] of stuur uw eigen tekenset in:

var randomValue = randomString(5);
var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');

Antwoord 9, autoriteit 2%

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

Antwoord 10, autoriteit 2%

Willekeurige stringgenerator (alfanumeriek | alfa | numeriek)

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

Antwoord 11

De eenvoudigste manier is:

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

Hiermee worden willekeurige reeksen van 5 tekens gegenereerd op basis van de huidige tijd. Voorbeelduitvoer is 4mtxjof 4mv90of 4mwp1

Het probleem hiermee is dat als je het twee keer op dezelfde seconde aanroept, het dezelfde string zal genereren.

De veiligere manier is:

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

Dit genereert een willekeurige reeks van 4 of 5 tekens, altijd verschillend. Voorbeelduitvoer is als 30jzmof 1r591of 4su1a

In beide opzichten genereert het eerste deel een willekeurig getal. Het .toString(36)deel wierp het getal naar een base36 (alfadecimale) representatie ervan.


Antwoord 12

Gebruik om aan eis [a-zA-Z0-9] en lengte=5 te voldoen

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

Kleine letters, hoofdletters en cijfers zullen voorkomen.


Antwoord 13

Ik weet dat iedereen het al goed heeft, maar ik had zin om dit op de meest lichtgewicht manier te proberen (licht op code, niet CPU):

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

Antwoord 14

Hier zijn enkele eenvoudige one-liners. Wijzig new Array(5)om de lengte in te stellen.

Inclusief 0-9a-z

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

Inclusief 0-9a-zA-Z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});

Antwoord 15

In het geval iemand geïnteresseerd is in een one-liner (hoewel niet zo geformatteerd voor uw gemak) die het geheugen in één keer toewijst (maar merk op dat het voor kleine strings echt niet uitmaakt), hier is hoe het te doen:

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

U kunt 5vervangen door de lengte van de gewenste reeks. Dank aan @ariyahidayat in dit bericht voor de oplossing Naar de mapFunctie werkt niet aan de sparse array gemaakt door Array(5).


Antwoord 16

Als u lodash of Underscore , dan zo eenvoudig:

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

Antwoord 17

Genereer een beveiligde willekeurige alfanumerieke Base-62String:

function generateUID(length)
{
    return window.btoa(Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2))).map((b) => String.fromCharCode(b)).join("")).replace(/[+/]/g, "").substring(0, length);
}
console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"

Antwoord 18

Hier is de methode die ik heb gemaakt.
Het creëert een tekenreeks met zowel hoofdletters als kleine letters.
Daarnaast heb ik de functie opgenomen die ook een alfanumerieke reeks heeft gemaakt.

werkvoorbeelden:
http://jsfiddle.net/greatbigmassive/vhsxs/(alleen alfa)
http://jsfiddle.net/greatbigmassive/PJwg8/(alfanumeriek)

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

Upgrade juli 2015
Dit doet hetzelfde, maar is logischer en omvat alle letters.

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

Antwoord 19

const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')

Antwoord 20

Verbeterd antwoord van @Andrew hierboven:

Array.from({ length : 1 }, () => Math.random().toString(36)[2]).join('');

Basis 36-conversie van het willekeurige getal is inconsistent, dus het selecteren van een enkele index lost dat op. Je kunt de lengte van een string wijzigen met de exacte gewenste lengte.


Antwoord 21

Ervan uitgaande dat u underscorejsgebruikt, is het mogelijk om op elegante wijze willekeurige tekenreeksen in slechts twee regels te genereren:

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

Antwoord 22

Eén voering:

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

Antwoord 23

Snel en verbeterd algoritme. Garandeert geen uniform (zie opmerkingen).

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

Antwoord 24

Wat dacht je van dit compacte trucje?

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

U hebt de Array.applyEr om de lege array te misleiden als een reeks undefineds.

Als u codeert voor ES2015, dan is het bouwen van de array een beetje eenvoudiger:

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

Antwoord 25

U kunt door een reeks items lopen en deze recursief toevoegen aan een tekenreeksvariabele, bijvoorbeeld als u een willekeurige DNA-sequentie wilde:

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

Antwoord 26

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

Dit is net zo schoon als het zal krijgen. Het is snel, http://jsperf.com/ay-random-string .


Antwoord 27

Het probleem met antwoorden op “Ik heb willekeurige strings nodig”-vragen (in welke taal dan ook) is dat praktisch elke oplossing een gebrekkige primaire specificatie van stringlengtegebruikt. De vragen zelf onthullen zelden waarom de willekeurige strings nodig zijn, maar ik daag uit dat je zelden willekeurige strings met een lengte van bijvoorbeeld 8 nodig hebt. Wat je altijd nodig hebt, is een aantal unieke strings, bijvoorbeeld om te gebruiken als identifiers voor een bepaald doel.

Er zijn twee manieren om strikt uniekestrings te krijgen: deterministisch (wat niet willekeurig is) en opslaan/vergelijken (wat lastig is). Wat doen we? Wij geven de geest. We gaan in plaats daarvan voor probabilistische uniciteit. Dat wil zeggen, we accepteren dat er een (hoe klein) risico ook is dat onze strings niet uniek zijn. Dit is waar het begrijpen van botsingskansen entropyzijn nuttig.

Dus ik herformuleer de onveranderlijke behoefte als een aantal snaren nodig met een klein risico op herhaling. Laten we als concreet voorbeeld zeggen dat u een potentieel van 5 miljoen ID’s wilt genereren. U wilt niet elke nieuwe reeks opslaan en vergelijken, en u wilt dat ze willekeurig zijn, dus u accepteert enig risico op herhaling. Laten we als voorbeeld zeggen een risico van minder dan 1 op een biljoen kans op herhaling. Dus welke lengte touw heb je nodig? Welnu, die vraag is ondergespecificeerd omdat het afhangt van de gebruikte tekens. Maar belangrijker nog, het is misplaatst. Wat je nodig hebt, is een specificatie van de entropie van de snaren, niet hun lengte. Entropie kan direct worden gerelateerd aan de waarschijnlijkheid van een herhaling in een aantal strings. Stringlengte kan niet.

en dit is waar een bibliotheek zoals Entropystring kan helpen. Om willekeurige ID’s te genereren die minder dan 1 hebben in een biljoen kans op herhaling in 5 miljoen snaren met entropy-string:

import {Random, Entropy} from 'entropy-string'
const random = new Random()
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)

“44htnhjnhggrhqh9”

entropy-stringGebruikt standaard een tekenset met 32 ​​tekens. Er zijn andere vooraf gedefinieerde tekensets en u kunt ook uw eigen personages opgeven. Bijvoorbeeld het genereren van ID’s met dezelfde entropie zoals hierboven, maar met behulp van hex-tekens:

import {Random, Entropy, charSet16} from './entropy-string'
const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)

“27b33372ADE513715481F”

Let op het verschil in stringlengte als gevolg van het verschil in totaal aantal tekens in de gebruikte tekenset. Het risico van herhaling in het opgegeven aantal potentiële snaren is hetzelfde. De snaarlengtes zijn dat niet. En het beste van alles, het risico van herhaling en het potentiële aantal snaren is expliciet. Niet meer gok met stringlengte.


Antwoord 28

Case ongevoelige alfanumerieke tekens:

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

Antwoord 29

Ik heb geen schone oplossing gevonden voor het ondersteunen van zowel kleine letters als hoofdletters.

Kleine letters alleen ondersteuning:

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

bouwen op die oplossing om kleine letters en hoofdletters te ondersteunen:

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

Wijzig de 5in substr(2, 5)om aan te passen aan de lengte die u nodig hebt.


ANTWOORD 30

één voering [A-Z]:

String.fromCharCode(97 + Math.floor(Math.random() * 26))

Other episodes