起因
对于随机不反复字符串,如果没有长度限度,那么最简略的办法 以后工夫戳 + 固定位数随机字符串
的模式齐全能够满足(仍有概率反复,但简直能够疏忽),至于长度,有很多方法解决,但最终也无奈做到很短。
最近公司有个小需要,把邀请码升高到四位,四位不反复邀请码的实现形式就不那么随便了,直观的想法是通过 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 '';
}