是否可以使用 JavaScript / jQuery 进行 base 36 编码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9542726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 07:01:24  来源:igfitidea点击:

Is it possible to base 36 encode with JavaScript / jQuery?

javascriptjquery

提问by AnApprentice

I'm thinking about using the encode/decode technique here (Encoding to base 36/decoding from base 36 is simple in Ruby)

我正在考虑在这里使用编码/解码技术(编码到 base 36/从 base 36 解码在 Ruby 中很简单)

how to implement a short url like urls in twitter?

如何在 twitter 中实现像 urls 这样的短 url?

Idea being to track user referrals, invite URLs. I can use Rails to decode, but it there a way to encode with Javascript or jQuery?

想法是跟踪用户推荐,邀请 URL。我可以使用 Rails 进行解码,但有没有办法使用 Javascript 或 jQuery 进行编码?

回答by Amadan

The toStringmethod on Numberhas an optional argument of radix:

toString方法对Number具有基数的可选参数:

(128482).toString(36);
128482..toString(36);
128482 .toString(36);
var num = 128482; num.toString(36);

Note this doesn't work, because numbers expect decimal digits after a period, not letters:

请注意,这不起作用,因为数字在句点后需要十进制数字,而不是字母:

128482.toString(36);  // Syntax error

Also, you can decode with JS as well:

此外,您也可以使用 JS 进行解码:

parseInt("2r4y", 36);

EDIT:

编辑:

But if I want to remove look-alike characters (1-l or 0-O) what can I do?

但是如果我想删除相似的字符(1-l 或 0-O),我该怎么办?

The easiest is to reduce the base by number of characters you're skipping, then make a translation: Note that only one of 1-lor 0-Ois a problem, since base36 encodes only lowercase (in which case you have 1-l, but not 0-O) which you can make uppercase (in which case, vice versa).

最简单的方法是根据要跳过的字符数减少基数,然后进行翻译:请注意,只有一个1-lor0-O是一个问题,因为 base36 仅编码小写字母(在这种情况下,您可以使用1-l,但不是0-O)大写(在这种情况下,反之亦然)。

(128482).toString(36).replace(/[m-y]/, x => String.fromCharCode(x.charCodeAt(0) + 1))

If you want to have a base larger than 36, you would have to have your own base-changing function, as 36 is as high as toStringsupports. In that case, it is easy enough to make your own digit inventory as you want.

如果你想要一个大于 36 的基数,你就必须有自己的变基功能,因为 36 和toString支撑一样高。在这种情况下,根据需要制作自己的数字库存很容易。

for working with long numbers?

用于处理长数字?

Go ahead :) Note the nsuffix that turns the number into BigInt:

继续 :) 请注意n将数字转换为的后缀BigInt

1000000000000000000000000000000000000000000000000000000000n.toString(36)
// => "9edwccv83mch429oxmlxupo4z1bdaiusrm29s"

回答by imjosh

For anyone looking for how to encode a stringin base36 (since this question, How do i convert string to base36 in javascript, is redirected here) -

对于任何寻找如何在 base36 中编码字符串的人(因为这个问题,How do i convert string to base36 in javascript,被重定向到这里) -

Here's what I came up with.

这是我想出的。

/* encode / decode strings to / from base36 

   based on: http://snipplr.com/view/12653/
*/

var base36 = {
    encode: function (str) {
        return Array.prototype.map.call(str, function (c) {
            return c.charCodeAt(0).toString(36);
        }).join("");
    },
    decode: function (str) {
        //assumes one character base36 strings have been zero padded by encodeAscii
        var chunked = [];
        for (var i = 0; i < str.length; i = i + 2) {
            chunked[i] = String.fromCharCode(parseInt(str[i] + str[i + 1], 36));
        }
        return chunked.join("");
    },
    encodeAscii: function (str) {
        return Array.prototype.map.call(str, function (c) {
            var b36 = base36.encode(c, "");
            if (b36.length === 1) {
                b36 = "0" + b36;
            }
            return b36;
        }).join("")
    },
    decodeAscii: function (str) {
        //ignores special characters/seperators if they're included
        return str.replace(/[a-z0-9]{2}/gi, function (s) {
            return base36.decode(s);
        })
    }
};

var foo = "a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~";
var bar = base36.encodeAscii(foo);

console.log(foo);
console.log(base36.decode(bar));

console.log('');

var bar = "==/" + bar + "\==";
console.log(bar)
console.log(base36.decodeAscii(bar));


//doesn't work
console.log('');
var myString = "some string";
var myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

myString = "FooBarW000t";
myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

myString = "aAzZ09!@#$%^&*()-_=+[{]};:',<.>/?`~";
myNum = parseInt(myString, 36);
console.log(myNum.toString(36))

/* 
Outputs:

a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~
a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~

==/2p191t3e192i0w1c191l0w0x1s0z10112m12161415192n1p172j3f2l3h1n1m13181o1a1q1b1r2o3i\==
==/a-Az-Z 0-9 !@#$%^&*()-_=+[{]};:',<.>/?`~\==

some
foobarw000w
aazz09
*/

回答by Eric D'Souza

For anyone looking to decode @imjosh's answer in python (say if you've encoded client-side and need to decode server-side), this is what I used. I would have left as a comment in @imjosh's answer but comments don't format very well.

对于任何希望在 python 中解码 @imjosh 答案的人(假设您已经对客户端进行了编码并且需要对服务器端进行解码),这就是我使用的。我会在@imjosh 的回答中留下评论,但评论的格式不是很好。

def decodeBase36(str):
  decoded_str = ""
  for i in range(0, len(str), 2):
    char = chr(int(str[i:i+2], 36))
    decoded_str += char
  return decoded_str

and a not-as-elegant Objective-C version:

和一个不那么优雅的 Objective-C 版本:

+ (NSString *)b36DecodeString:(NSString *)b36String
{
    NSMutableString *decodedString = [NSMutableString stringWithFormat:@""];
    for (int i = 0; i < [b36String length]; i+=2) {
        NSString *b36Char = [b36String substringWithRange:NSMakeRange(i, 2)];
        int asciiCode = 0;
        for (int j = 0; j < 2; j++) {
            int v = [b36Char characterAtIndex:j];
            asciiCode += ((v < 65) ? (v - 48) : (v - 97 + 10)) * (int)pow(36, 1 - j);
        }
        [decodedString appendString:[NSString stringWithFormat:@"%c", asciiCode]];
    }
    return decodedString;
}

回答by marko-36

I wrote this baseXY shortener, designed for a very similar question/need I had:

我写了这个 baseXY 缩短器,专为我遇到的一个非常相似的问题/需求而设计:

https://github.com/marko-36/base29-shortener.

https://github.com/marko-36/base29-shortener

  • By default, in order to leave out easily interchangeable characters, it is a base29shortener, but the 'XY' number is the same as number of characters you decide to use for encoding.
  • Since the set of characters is fully customizable, you can omit any you wish (i, l, 1, L, o, 0, O..)
  • To make it less obvious, what the encoding character set is, and/or if you want the encoding string to have a minimal length, just start encoding from a high enough number.
  • 默认情况下,为了省去容易互换的字符,它是一个基数为29 的缩短器,但“ XY”数字与您决定用于编码的字符数相同。
  • 由于字符集是完全可定制的,因此您可以省略任何您希望的字符 ( i, l, 1, L, o, 0, O..)
  • 为了不那么明显,编码字符集是什么,和/或如果您希望编码字符串具有最小长度,只需从足够大的数字开始编码。

This is it, hope it helps:

就是这样,希望它有帮助:

    const c=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '2', '3', '4', '5', '6', '7', '8', '9']; 
    //characters for encoding

    function to29(i){
        var sLen = Math.floor(Math.log(i)/Math.log(c.length)) +1;
        var s = '';
        for(ex=sLen-1; ex>-1; --ex){
            s += c[Math.floor(i / Math.pow(c.length,ex))];
            i = [i % Math.pow(c.length,ex)];
        }
        return s;
    }

    function from29(s){
        var i = 0;
        for (ex=0; ex<s.length; ++ex){
            i += c.indexOf(s.substring(ex,ex+1))*Math.pow(c.length,s.length-1-ex);
        }
        return i;
    }