起因
对于随机不反复字符串,如果没有长度限度,那么最简略的办法以后工夫戳 + 固定位数随机字符串
的模式齐全能够满足(仍有概率反复,但简直能够疏忽),至于长度,有很多方法解决,但最终也无奈做到很短。
最近公司有个小需要,把邀请码升高到四位,四位不反复邀请码的实现形式就不那么随便了,直观的想法是通过10个数字(0-9) + 26个小写字母(a-z)排列组合实现,即所谓的排列可反复问题。
这类问题公式如下,每次n种抉择,抉择r次的排列共有:n的r次幂。这很好了解,一次有n种抉择,第二次有n∗n种抉择,……,第r次有nr种抉择。
对应咱们的需要,也就是能够有36的4次幂 = 1679616种组合,齐全能够满足一个小型我的项目的需要。如果我的项目比拟大,齐全能够通过退出其余项(比方特殊字符、大写字母等等)到可择列表实现,最终还能够晋升邀请码位数进一步扩大。
思路比拟直观简略,但也比拟实用,欢送大家学习交换。
实现
思路:
1、首先要确定随机数的根据,采纳递增数字(能够对应数据库id)作为根底,创立随机串。
2、打乱10个数字 + 26个字母的组合,这样随机数看起来会难受一些。
3、把基数转换成36进制数字,转换后有余4位则补充0位。
4、把四位数字的每一位作为下标对应打乱后10个数字 + 26个字母的组合的列表。
5、组合成4位惟一随机字符串。
上面是代码:
exports.random = (number) => { // 打乱的10个数字 + 26个字母 const arr = ["m","0","j","f","8","o","z","w","5","t","p","a","1","d","s","h","v","x","9","b","r","y","2","e","7","4","3","q","6","n","u","l","c","g","i","k"]; // 把number由十进制数转换成36进制数 const transNumber = binaryConversion(+number, 10, 36); // 排除大于4位的状况 const len = transNumber.toString().length; if (len > 4) { console.log('数字过大'); return; } // 转换后的数字有余4位则补充0位,并按字符转换成数组 const list = prefixInteger(transNumber, 4).toString().split(''); const len4Arr = []; for (const num of list) { // 判断以后字符是数字还是字母 const type = checkStrType(num); // 如果是数字不解决,如果是字母则转换成对应的数组(10 - 35) const index = type === 'string' ? stringTonum(num) + 9 : num; len4Arr.push(arr[+index]); } // 返回后果 return len4Arr.join('');}
补充
毛病:基数数字低于36无奈创立,比方起始数字大于36。
欢送大家提出高效思路,不足之处请指出。
其余代码如下:
function binaryConversion(num, m ,n) { return parseInt(String(num), m).toString(n);}function prefixInteger(num, length) { return (Array(length).join('0') + num).slice(-length);}function stringTonum(a) { const str = a.toLowerCase().split(''); const al = str.length; const getCharNumber = charx => charx.charCodeAt() - 96; let numout = 0; let charnum = 0; for (let i = 0; i < al; i++) { charnum = getCharNumber(str[i]); numout += charnum * Math.pow(26, al - i - 1); }; return numout;}function checkStrType(str) { //验证是否是英文 var pattern = new RegExp("[A-Za-z]+"); if (pattern.test(str)) return 'string'; //验证是否是数字 var patternNumber = new RegExp("[0-9]+"); if (patternNumber.test(str)) return 'number'; return '';}