如何将uuid缩短并扩展为15个或更少的字符
给定一个没有短划线的uuid(v4),如何将其缩短为15个或少于15个字符的字符串?我也应该能够从15个字符的字符串返回到原始的uuid。
我试图缩短它以将其发送到平面文件中,文件格式将此字段指定为15个字符的字母数字字段。鉴于缩短的uuid,我应该能够将它映射回原始的uuid。
这是我尝试过的,但绝对不是我想要的。
export function shortenUUID(uuidToShorten: string, length: number) {
const uuidWithoutDashes = uuidToShorten.replace(/-/g , '');
const radix = uuidWithoutDashes.length;
const randomId = [];
for (let i = 0; i < length; i++) {
randomId[i] = uuidWithoutDashes[ 0 | Math.random() * radix];
}
return randomId.join('');
}
回答如下:
正如AuxTaco指出的那样,如果你实际上是指“字母数字”,因为它匹配“/ ^ [A-Za-z0-9] {0,15} /”(给出的位数为26 + 26 + 10 = 62)那真是不可能。你不能在一加仑桶中装入3加仑的水而不会丢失一些东西。 UUID是128位,因此要将其转换为62的字符空间,您至少需要22个字符(log[base 62](2^128)
== ~22)。
如果你的charset更灵活,只需要15个unicode字符就可以放入文本文档,那么我的回答会有所帮助。
注意:这个答案的第一部分,我认为它的长度为16,而不是15.更简单的答案是行不通的。下面更复杂的版本仍然会。
为此,您需要使用某种双向压缩算法(类似于用于压缩文件的算法)。
但是,尝试压缩类似UUID的问题是你可能会遇到很多冲突。
UUID v4长度为32个字符(不带短划线)。它是十六进制的,所以它的字符空间是16个字符(0123456789ABCDEF
)
这给你一些可能的组合16^32
,大约3.4028237e+38
或340,282,370,000,000,000,000,000,000,000,000,000,000
。要使其在压缩后可恢复,您必须确保没有任何冲突(即,没有2个UUID变成相同的值)。这是很多可能的值(这正是我们为UUID使用那么多的原因,2个随机UUID的概率只是该数字大数的1)。
要将这么多可能性压缩到16个字符,你必须至少拥有尽可能多的可能值。有16个字符,你必须有256个字符(该大数字的根16,256^16
== 16 ^ 32`)。假设你有一个永远不会产生碰撞的算法。
确保永远不会发生冲突的一种方法是将其从base-16编号转换为base-256编号。这将给你一对一的关系,确保没有碰撞并使其完全可逆。通常,在JavaScript中切换基础很简单:parseInt(someStr, radix).toString(otherRadix)
(例如,parseInt('00FF', 16).toString(20)
。不幸的是,JavaScript只能达到36的基数,所以我们必须自己进行转换。
如此庞大的基地的捕获代表它。您可以随意选择256个不同的字符,将它们放入一个字符串中,然后将其用于手动转换。但是,我不认为标准美国键盘上有256个不同的符号,即使您将大写和小写视为不同的字形。
一个更简单的解决方案是使用0
中的任意字符代码和255
的String.fromCharCode()
。
另一个小问题是,如果我们试图将所有这些都视为一个大数字,我们就会遇到问题,因为它是一个非常大的数字,JavaScript无法正确地表示它。
而不是那样,因为我们已经有了十六进制,我们可以将它分成几对小数,转换它们,然后将它们吐出来。 32个十六进制数字= 16对,因此(巧合)是完美的。 (如果您必须以任意大小解决此问题,则必须进行一些额外的数学运算并转换为将数字拆分为多个,转换,然后重新组合。)
const uuid = '1234567890ABCDEF1234567890ABCDEF';
const letters = uuid.match(/.{2}/g).map(pair => String.fromCharCode(parseInt(pair, 16)));
const str = letters.join('');
console.log(str);
如何将uuid缩短并扩展为15个或更少的字符
给定一个没有短划线的uuid(v4),如何将其缩短为15个或少于15个字符的字符串?我也应该能够从15个字符的字符串返回到原始的uuid。
我试图缩短它以将其发送到平面文件中,文件格式将此字段指定为15个字符的字母数字字段。鉴于缩短的uuid,我应该能够将它映射回原始的uuid。
这是我尝试过的,但绝对不是我想要的。
export function shortenUUID(uuidToShorten: string, length: number) {
const uuidWithoutDashes = uuidToShorten.replace(/-/g , '');
const radix = uuidWithoutDashes.length;
const randomId = [];
for (let i = 0; i < length; i++) {
randomId[i] = uuidWithoutDashes[ 0 | Math.random() * radix];
}
return randomId.join('');
}
回答如下:
正如AuxTaco指出的那样,如果你实际上是指“字母数字”,因为它匹配“/ ^ [A-Za-z0-9] {0,15} /”(给出的位数为26 + 26 + 10 = 62)那真是不可能。你不能在一加仑桶中装入3加仑的水而不会丢失一些东西。 UUID是128位,因此要将其转换为62的字符空间,您至少需要22个字符(log[base 62](2^128)
== ~22)。
如果你的charset更灵活,只需要15个unicode字符就可以放入文本文档,那么我的回答会有所帮助。
注意:这个答案的第一部分,我认为它的长度为16,而不是15.更简单的答案是行不通的。下面更复杂的版本仍然会。
为此,您需要使用某种双向压缩算法(类似于用于压缩文件的算法)。
但是,尝试压缩类似UUID的问题是你可能会遇到很多冲突。
UUID v4长度为32个字符(不带短划线)。它是十六进制的,所以它的字符空间是16个字符(0123456789ABCDEF
)
这给你一些可能的组合16^32
,大约3.4028237e+38
或340,282,370,000,000,000,000,000,000,000,000,000,000
。要使其在压缩后可恢复,您必须确保没有任何冲突(即,没有2个UUID变成相同的值)。这是很多可能的值(这正是我们为UUID使用那么多的原因,2个随机UUID的概率只是该数字大数的1)。
要将这么多可能性压缩到16个字符,你必须至少拥有尽可能多的可能值。有16个字符,你必须有256个字符(该大数字的根16,256^16
== 16 ^ 32`)。假设你有一个永远不会产生碰撞的算法。
确保永远不会发生冲突的一种方法是将其从base-16编号转换为base-256编号。这将给你一对一的关系,确保没有碰撞并使其完全可逆。通常,在JavaScript中切换基础很简单:parseInt(someStr, radix).toString(otherRadix)
(例如,parseInt('00FF', 16).toString(20)
。不幸的是,JavaScript只能达到36的基数,所以我们必须自己进行转换。
如此庞大的基地的捕获代表它。您可以随意选择256个不同的字符,将它们放入一个字符串中,然后将其用于手动转换。但是,我不认为标准美国键盘上有256个不同的符号,即使您将大写和小写视为不同的字形。
一个更简单的解决方案是使用0
中的任意字符代码和255
的String.fromCharCode()
。
另一个小问题是,如果我们试图将所有这些都视为一个大数字,我们就会遇到问题,因为它是一个非常大的数字,JavaScript无法正确地表示它。
而不是那样,因为我们已经有了十六进制,我们可以将它分成几对小数,转换它们,然后将它们吐出来。 32个十六进制数字= 16对,因此(巧合)是完美的。 (如果您必须以任意大小解决此问题,则必须进行一些额外的数学运算并转换为将数字拆分为多个,转换,然后重新组合。)
const uuid = '1234567890ABCDEF1234567890ABCDEF';
const letters = uuid.match(/.{2}/g).map(pair => String.fromCharCode(parseInt(pair, 16)));
const str = letters.join('');
console.log(str);