【问题标题】:Convert a number to the shortest possible character string while retaining uniqueness将数字转换为尽可能短的字符串,同时保持唯一性
【发布时间】:2010-04-01 00:52:57
【问题描述】:

我有一个数字,比如“123456”,我需要将它映射到一个字符串,任何字符串。地图功能的唯一限制是:

  • 每个数字必须映射到唯一的字符串(这意味着字符串可以任意长)
  • 字符串只能包含0-9、a-z、A-Z

什么映射函数会产生最短的字符串?

首选 JavaScript 解决方案。

注意:显然,最简单的解决方案是使用原始数字,因此请确保您的解决方案做得更好。

【问题讨论】:

  • 您说的是“数字列表”而不是“数字”。这是否意味着您希望将“000006”与“6”区别对待?
  • 一个好问题。不,我没有。我会更正它以使其更清楚。

标签: javascript


【解决方案1】:

您可能想要使用 Base 36Base 62

Base 36 对于不区分大小写的字母数字字符来说是最紧凑的,但如果您想利用大小写敏感性,Base 62 的紧凑度大约会提高 20%。

对于Base 36,可以很方便的使用JavaScript的Number.toString(radix)方法,如下:

var n = 123456;
n.toString(36); // returns: "2n9c"

对于 Base 62,您可能需要检查 this forum post。基本上你应该能够做到以下几点:

Number.prototype.toBase = function (base) {
    var symbols = 
    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
    var decimal = this;
    var conversion = "";

    if (base > symbols.length || base <= 1) {
        return false;
    }

    while (decimal >= 1) {
        conversion = symbols[(decimal - (base * Math.floor(decimal / base)))] + 
                     conversion;
        decimal = Math.floor(decimal / base);
    }

    return (base < 11) ? parseInt(conversion) : conversion;
}

var n = 123456;
n.toBase(62); // returns: "w7e"

【讨论】:

  • 除非我弄错了,否则 OP 需要 base 62。
  • @spender:是的,你是对的,因为明确提到了 A-Z。修改了我的答案。
  • 123456.toString(36) 确实满足要求...可惜它不做base 62,那会更好。
  • 你计算了两次Math.floor(decimal / base),最后我不会调用parseInt,我会抛出 RangeError 异常而不是返回 false。
  • parseInt('2n9c', 36)
【解决方案2】:

我这样做是为了创建类似 YouTube 的密钥。它使用正则表达式来捕获数字,然后在匹配列表中循环以组装字符串。

chars 数组的顺序是任意的,实际上你可以随意设置它,但是一旦设置好,以后不要更改它,否则你可能会遇到重复的键,并确保你不要'没有任何重复。

这里的 num 是保存输入键的变量。在这个示例中它很长,但它可以是任意长度。

var chars = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
num = "000102030405060708091011121314151617181920212223242526272829303132333435373839404142434445464748495051525354555657585960616263646566";
getnums = num.match(/(0|6[0-1]|[0-5]?[0-9])/g);
to62 = "";
for (var i=0;i<getnums.length;i++) {
    to62 = to62 + chars[parseInt(getnums[i])];
    // console.log(getnums[i] + ": " + chars[parseInt(getnums[i])])
}
console.log(to62);

这是 Cold Fusion 中的一个实现,它使用基于 1 的数组,而不是 javascript 的基于 0 的数组,以防它对任何人有所帮助。

<cfscript>
  chars = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
  num = "0001020304050607080910111213141516171819202122232425262728293031323334353738394041424344454614748495051525354555657585960616263646566";
  getnums = ReMatch("(0|6[0-1]|[0-5]?[0-9])",num);
  to62 = "";
  for (i=1; i<=arraylen(getnums); i=i+1) {
      to62 = to62 & chars[getnums[i]+1];
  }
  writeoutput(to62);
</cfscript>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    • 2022-01-18
    • 2021-01-09
    • 2016-11-03
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多