ฉันต้องการสตริง 5 [a-zA-Z0-9]
ตัวอักษรประกอบด้วยตัวอักษรสุ่มเลือกจากชุดที่
วิธีที่ดีที่สุดในการทำเช่นนี้กับ JavaScript คืออะไร?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
ฉันต้องการสตริง 5 [a-zA-Z0-9]
ตัวอักษรประกอบด้วยตัวอักษรสุ่มเลือกจากชุดที่
วิธีที่ดีที่สุดในการทำเช่นนี้กับ JavaScript คืออะไร?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
คำตอบ:
ฉันคิดว่าสิ่งนี้จะได้ผลสำหรับคุณ:
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));
+=
กับสตริงเช่นนี้ทำให้เกิดพฤติกรรม O (n ^ 2) หากคุณต้องการสร้างสตริงที่ยาวขึ้นคุณควรสร้างอาร์เรย์ของอักขระแต่ละตัวและรวมเข้าด้วยกันในตอนท้าย
+=
มักจะเร็วกว่าด้วยเหตุผลบางอย่างแม้แต่ใช้ในลูป - jsperf.com/join-vs-concatenation
crypto
แทน
let r = Math.random().toString(36).substring(7);
console.log("random", r);
หมายเหตุ: อัลกอริทึมด้านบนมีจุดอ่อนดังต่อไปนี้:
Math.random()
อาจสร้างผลลัพธ์ที่คาดการณ์ได้ ("ดูสุ่ม" แต่ไม่สุ่มจริง ๆ ) ขึ้นอยู่กับการใช้งาน สายอักขระผลลัพธ์ไม่เหมาะสมเมื่อคุณต้องการรับประกันความเป็นเอกลักษณ์หรือความคาดเดาไม่ได้Math.random().toString(36).substr(2, 5)
เนื่องจาก.substring(7)
ทำให้มีความยาวเกิน 5 อักขระ คะแนนเต็มยัง!
toString
วิธีการของประเภทตัวเลขในจาวาสคริปต์ใช้พารามิเตอร์ตัวเลือกในการแปลงตัวเลขเป็นฐานที่กำหนด ตัวอย่างเช่นถ้าคุณผ่านสองตัวอย่างคุณจะเห็นหมายเลขของคุณแสดงเป็นเลขฐานสอง เช่นเดียวกับฐานสิบหก (ฐาน 16) ฐานหก 36 ใช้ตัวอักษรเพื่อแทนตัวเลขที่เกิน 9 ด้วยการแปลงตัวเลขสุ่มเป็นฐาน 36 คุณจะจบลงด้วยการสุ่มตัวอักษรและตัวเลข
(Math.random() + 1).toString(36).substring(7);
คณิตศาสตร์แบบสุ่มไม่ดีสำหรับสิ่งนี้
ตัวเลือกที่ 1
หากคุณสามารถทำเซิร์ฟเวอร์นี้ได้เพียงใช้โมดูลcrypto
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
.map()
ในทางเลือกที่ 3 ===Array.from(arr, dec2hex).join('')
Array.from(arr).map(dec2hex).join('')
ขอขอบคุณที่แนะนำฉันให้รู้จักกับคุณสมบัติเหล่านี้ :-)
require
โมดูลเท่านั้นที่จะสามารถที่จะเป็นด้านเซิร์ฟเวอร์ที่ใช้?
ส่งคืนอักขระสุ่ม 5 ตัวตรงข้ามกับคำตอบที่ได้รับความนิยมสูงสุดที่นี่
Math.random().toString(36).substr(2, 5);
Math.random().toString(36)
ส่งคืนตัวเลขที่มีอักขระน้อยกว่า 5 ตัว
function getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
นี่คือการปรับปรุงในคำตอบที่ดีเยี่ยมของ doubletap ต้นฉบับมีข้อบกพร่องสองประการที่กล่าวถึงที่นี่:
อันดับแรกตามที่คนอื่น ๆ พูดถึงมันมีความเป็นไปได้น้อยมากที่จะสร้างสตริงสั้น ๆ หรือแม้แต่สตริงว่างเปล่า (ถ้าตัวเลขสุ่มเป็น 0) ซึ่งอาจทำให้แอปพลิเคชันของคุณเสียหาย นี่คือทางออก:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
ประการที่สองทั้งต้นฉบับและโซลูชันด้านบน จำกัด ขนาดสตริง N ถึง 16 อักขระ ต่อไปนี้จะส่งคืนสตริงที่มีขนาด N สำหรับ N ใด ๆ (แต่โปรดทราบว่าการใช้ N> 16 จะไม่เพิ่มการสุ่มหรือลดความน่าจะเป็นของการชน):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
คำอธิบาย:
ความคิดเพิ่มเติม:
ปรับปรุง:
ต่อไปนี้เป็นรูปแบบการทำงานอื่น ๆ ที่ฉันใช้ด้วย พวกเขาแตกต่างจากการแก้ปัญหาข้างต้นในที่:
ดังนั้นพูดตัวอักษรที่คุณเลือกคือ
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
จากนั้นทั้งสองนี้จะเทียบเท่ากันดังนั้นคุณสามารถเลือกได้ว่าคุณจะใช้วิธีใดให้ง่ายขึ้น:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
และ
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
แก้ไข:
ฉันดูเหมือนว่าqubyteและMartijn de Millianoมาพร้อมกับวิธีแก้ปัญหาที่คล้ายคลึงกับหลัง (รุ่งโรจน์!) ซึ่งฉันก็พลาดไป เนื่องจากพวกเขาไม่ได้มองสั้น ๆ ฉันจะทิ้งไว้ที่นี่ต่อไปในกรณีที่มีคนต้องการหนึ่งซับ :-)
นอกจากนี้แทนที่ 'new Array' ด้วย 'Array' ในโซลูชันทั้งหมดเพื่อกำจัดจำนวนไบต์ไม่กี่ไบต์
(Math.random()+1).toString(36).substring(7);
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('')
วิธีการแก้ปัญหาที่มีขนาดกะทัดรัดมากที่สุดเพราะจะสั้นกว่า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"
;)
Math.random()
ผลตอบแทนผลที่ได้คือ0.5
"0.i"
ไม่แน่ใจว่ามีกรณีขอบอื่น ๆ หรือไม่ แค่ต้องการชี้ให้เห็นว่านี่ไม่ใช่คำตอบที่ถูกต้องสำหรับคำถาม (5 ตัวอักษรจาก [a-zA-Z0-9])
(+new Date + Math.random())
เพื่อป้องกันกรณีนี้ อย่างไรก็ตามขอขอบคุณสำหรับการบันทึก
สิ่งนี้จะทำงานได้ดี
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
วง
รุ่นที่ใหม่กว่าพร้อมตัวดำเนินการes6 :
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
เป็นจำนวนพลคุณสามารถเลือกระยะเวลาในโทเค็นที่คุณต้องการ36
คือหมายเลข Radix สูงสุดที่คุณสามารถส่งไปยังnumeric.toString ()ซึ่งหมายถึงตัวเลขทั้งหมดและตัวอักษรตัวพิมพ์เล็ก az2
จะใช้ในการรับดัชนีที่ 3 จากสตริงแบบสุ่มซึ่งมีลักษณะเช่นนี้"0.mfbiohx64i"
เราอาจจะใช้ดัชนีใด ๆ หลังจากที่0.
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(L--)
จะทำ
'A'.charCodeAt(0)
มากกว่าจำนวนเวทย์มนตร์55
(และเช่นเดียวกันสำหรับ61
) 65
โดยเฉพาะอย่างยิ่งตั้งแต่บนแพลตฟอร์มอยู่ดีของฉันจำนวนมายากลที่เป็นผลตอบแทน รหัสนั้นจะดีกว่าเอกสารด้วยตนเองเช่นกัน
/**
* 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 ที่ต้องการลองแบ่งมันออกเป็นส่วนที่จำเป็น (เฉพาะตัวเลขอัลฟ่าเท่านั้น) เพื่อความเข้าใจที่ดีขึ้น:
var str = "";
เชื่อมโยงอักขระสุ่มrand
หมายเลขดัชนีจาก0 ถึง 61 (0..9 + A..Z + a..z = 62)rand
(เนื่องจากเป็น 0..61) การเพิ่มขึ้นด้วยตัวเลขบางตัว (ดูตัวอย่างด้านล่าง) เพื่อรับกลับCharCode
หมายเลขที่ถูกต้องและตัวละครที่เกี่ยวข้องstr
aString.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))
วิธีที่ง่ายที่สุดคือ:
(new Date%9e6).toString(36)
สิ่งนี้จะสร้างสตริงสุ่ม 5 ตัวอักษรตามเวลาปัจจุบัน ตัวอย่างการแสดงผลเป็น4mtxj
หรือ4mv90
หรือ4mwp1
ปัญหานี้คือถ้าคุณเรียกมันสองครั้งในวินาทีเดียวกันมันจะสร้างสตริงเดียวกัน
วิธีที่ปลอดภัยกว่าคือ:
(0|Math.random()*9e6).toString(36)
สิ่งนี้จะสร้างสตริงแบบสุ่มที่มีอักขระ 4 หรือ 5 ตัวแตกต่างกันเสมอ ตัวอย่างการแสดงผลเป็นเหมือน30jzm
หรือ1r591
หรือ4su1a
ในทั้งสองวิธีส่วนแรกสร้างตัวเลขสุ่ม .toString(36)
ส่วนหนึ่งโยนตัวเลขเพื่อเป็นตัวแทน base36 (alphadecimal) ของมัน
(+new Date).toString(36)
(0|Math.random()*6.04e7).toString(36)
เพื่อให้ครอบคลุมได้
(Math.random()*1e20).toString(36)
(ไม่รวมระยะเวลา):
นี่คือ liners หนึ่งง่าย ๆ เปลี่ยน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"]();});
ฉันรู้ว่าทุกคนเข้าใจถูกต้องแล้ว แต่ฉันรู้สึกอยากไปที่นี่ด้วยวิธีที่เบาที่สุดเท่าที่จะเป็นไปได้ (เขียนรหัสไม่ใช่ซีพียู):
function rand(length, current) {
current = current ? current : '';
return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}
console.log(rand(5));
ต้องใช้เวลาสักครู่เพื่อตัดหัวของคุณ แต่ฉันคิดว่ามันแสดงให้เห็นว่าไวยากรณ์ของจาวาสคริปต์นั้นยอดเยี่ยมแค่ไหน
current = current ? current : '';
เมื่อคุณสามารถเขียนcurrent = current || ''
;
current || (current = '');
หากคุณใช้LodashหรือUnderscore แสดงว่าง่ายมาก:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
_.sampleSize('asdfgh',5).join('')
เพื่อตอบสนองความต้องการ [a-zA-Z0-9] และ length = 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)
นี่คือวิธีที่ฉันสร้าง
มันจะสร้างสตริงที่มีทั้งตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก
นอกจากนี้ฉันได้รวมฟังก์ชั่นที่จะสร้างสตริงตัวอักษรและตัวเลขด้วย
ตัวอย่างการทำงาน:
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;
}
อัปเกรดกรกฎาคม 2558
สิ่งนี้ทำในสิ่งเดียวกัน แต่มีเหตุผลมากกว่าและรวมถึงตัวอักษรทั้งหมด
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)));
}
สมมติว่าคุณใช้เครื่องหมายขีดล่างเป็นไปได้ที่จะสร้างสตริงแบบสุ่มอย่างหรูหราในสองบรรทัด:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
อัลกอริทึมที่รวดเร็วและปรับปรุง ไม่รับประกันเครื่องแบบ (ดูความคิดเห็น)
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;
}
crypto.getRandomValues
ส่งคืนค่าหนึ่งใน 256 ค่าที่ไม่ซ้ำกัน เนื่องจาก 256 ไม่หารด้วย 62 คุณจึงมีโอกาสสูงที่จะได้รับตัวอักษร AH เล็กน้อย ฉันคิดว่าทางออกที่ดีที่สุดคือทำในสิ่งที่ YouTube ทำและเพียงเพิ่มตัวละครเพิ่มเติมอีก 2 ตัว (อาจ-
และ_
) ลงในชุดอักขระ อย่างไรก็ตามการทำงานที่ดี - คำตอบนี้ต้องการความรักมากขึ้น :)
ปัญหาเกี่ยวกับการตอบสนองต่อ"ผมต้องสตริงสุ่ม"คำถาม (ในภาษาใด) เป็นวิธีการแก้ปัญหาในทางปฏิบัติทุกใช้สเปคหลักข้อบกพร่องของความยาวสาย คำถามตัวเองไม่ค่อยเปิดเผยว่าทำไมต้องมีสตริงสุ่ม แต่ฉันขอท้าให้คุณไม่ค่อยต้องการสตริงที่มีความยาวสุ่มบอกว่า 8 สิ่งที่คุณต้องการเสมอคือสตริงพิเศษจำนวนหนึ่งตัวอย่างเช่นใช้เป็นตัวระบุสำหรับวัตถุประสงค์บางอย่าง
มีสองวิธีที่นำไปสู่การได้รับสตริงที่ไม่ซ้ำกันอย่างเด็ดขาด : deterministically (ซึ่งไม่ได้สุ่ม) และเก็บ / เปรียบเทียบ (ซึ่งเป็นภาระ) พวกเราทำอะไร? พวกเรายอมแพ้ผี เราไปด้วยความน่าจะเป็นเอกลักษณ์แทน นั่นคือเรายอมรับว่ามีความเสี่ยง (เล็ก ๆ น้อย ๆ ) ที่สายของเราจะไม่ซ้ำกัน นี่คือที่การทำความเข้าใจความน่าจะเป็นของการชนและเอนโทรปีมีประโยชน์
ดังนั้นฉันจะใช้ความต้องการที่ไม่เปลี่ยนแปลงตลอดเวลาเพื่อต้องการสตริงจำนวนหนึ่งที่มีความเสี่ยงเล็กน้อยในการทำซ้ำ ตัวอย่างเช่นสมมติว่าคุณต้องการสร้างศักยภาพ 5 ล้าน ID คุณไม่ต้องการจัดเก็บและเปรียบเทียบแต่ละสตริงใหม่และคุณต้องการให้มันสุ่มดังนั้นคุณยอมรับความเสี่ยงในการทำซ้ำ ตัวอย่างเช่นสมมติว่ามีความเสี่ยงน้อยกว่า 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 อักขระโดยค่าเริ่มต้น มีชุดอักขระที่กำหนดไว้ล่วงหน้าอื่น ๆ และคุณสามารถระบุอักขระของคุณเองได้เช่นกัน ตัวอย่างเช่นการสร้าง ID ด้วยเอนโทรปีเดียวกันกับด้านบน แต่ใช้อักขระฐานสิบหก:
import {Random, Entropy, charSet16} from './entropy-string'
const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"27b33372ade513715481f"
บันทึกความแตกต่างของความยาวสตริงเนื่องจากความแตกต่างของจำนวนอักขระทั้งหมดในชุดอักขระที่ใช้ ความเสี่ยงในการทำซ้ำตามจำนวนสายอักขระที่ระบุอาจเหมือนกัน ความยาวสตริงไม่ใช่ และที่สำคัญที่สุดคือความเสี่ยงในการทำซ้ำและจำนวนสายอักขระที่ชัดเจน ไม่ต้องเดาอีกต่อไปกับความยาวสตริง
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--
แก้ไขให้ฉัน
คุณสามารถวนซ้ำอาร์เรย์ของรายการและเพิ่มไปยังตัวแปรสตริงซ้ำตัวอย่างเช่นหากคุณต้องการลำดับดีเอ็นเอแบบสุ่ม:
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
ในsubstr(2, 5)
การปรับความยาวได้ตามที่คุณต้องการ
หนึ่งในสายการบิน:
Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Array(15)
ค่าที่น้อยลง Array(4)
เช่น:
ใช้งานได้อย่างแน่นอน
<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>
สิ่งที่เกี่ยวกับเรื่องนี้: Date.now().toString(36)
ไม่สุ่มมาก แต่สั้นและไม่เหมือนใครทุกครั้งที่คุณเรียกมัน
Date.now()
มีความละเอียดเป็นมิลลิวินาทีเท่านั้น ยกตัวอย่างเช่นเมื่อทำงานในลูปธรรมดาคุณจะได้รับข้อมูลซ้ำซ้อนมากมาย for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }
.
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
ชอบในคำตอบที่ยอมรับได้ดังนั้นผลลัพธ์ของฟังก์ชันนั้นสามารถกำหนดค่าได้มากกว่า
สร้างสตริงที่มีความยาว 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;
}
คุณสามารถใช้coderain มันเป็นห้องสมุดในการสร้างรหัสสุ่มตามรูปแบบที่กำหนด ใช้#
เป็นตัวยึดตำแหน่งสำหรับอักขระส่วนบนและตัวพิมพ์เล็กรวมถึงตัวเลข:
var cr = new CodeRain("#####");
console.log(cr.next());
มีตัวยึดอื่น ๆ เช่นA
ตัวอักษรตัวพิมพ์ใหญ่หรือ9
ตัวเลข
สิ่งที่อาจมีประโยชน์คือการโทร.next()
จะให้ผลลัพธ์ที่เป็นเอกลักษณ์เสมอดังนั้นคุณไม่ต้องกังวลกับการซ้ำซ้อน
นี่คือโปรแกรมการสาธิตที่สร้างรายการของรหัสสุ่มที่ไม่ซ้ำกัน
การเปิดเผยแบบเต็ม: ฉันเป็นผู้เขียนโคเด็นain
true-random
ผล!pseudo-random
พวกเขาเป็นเพียง เมื่อใช้สตริงสุ่มสำหรับการป้องกันหรือรักษาความปลอดภัยอย่าใช้สายเหล่านี้ !!! ลองใช้หนึ่งใน api เหล่านี้: random.org