2011-05-21 56 views
1

第一件事:必須完全用javascript完成。 (jQuery/mootools可選)壓縮/ urlencode在JavaScript中的一系列100個基本4數字

我有一系列100個數字,每組0,1,2或3 - 這些代表頁面上的設置。我想將它們編碼爲儘可能最短的字符串以創建頁面的固定鏈接。

我想最好的方法是將它們存儲在二進制對聯中,將這些對聯轉換爲字符串,然後對字符串進行urlencode。

但是,我發現迄今爲止最好的是parseint(binary_var, 2),它將二進制數字轉換爲base_10數字。然而爲了讓字符串足夠短,我需要一個更好的系統。

如果我可以轉換爲64位編碼,我想可以將所有數據存儲在4個字符中。我知道URL現在支持Unicode,我相信我可以使用escapeunescape對64位字符進行編碼/解碼,所以我期待的主要方法是將二進制數據編碼/解碼爲64位字符。

當然,我不是100%肯定這是最好的方式,或者甚至會工作,所以我完全偏離了軌道,隨意指向正確的方向。

謝謝!

+0

這有什麼錯餅乾? – 2011-05-21 20:47:56

+0

@Tyler - 我不認爲餅乾可以創建永久鏈接... – jisaacstone 2011-05-21 21:02:44

回答

1

您可以數字,如陣列編碼成一個字符串,3元字符,像這樣:

function encodeBase4(base4) { 
    var i, rv = [], n = ~~((base4.length + 2)/3) * 3; 

    for (i = 0; i < n; i += 3) { 
    rv.push(
     32 + 
     ((base4[i] || 0) & 3) + 
     ((base4[i + 1] || 0) & 3) * 4 + 
     ((base4[i + 2] || 0) & 3) * 16 
    ); 
    } 

    return String.fromCharCode.apply(null, rv); 
} 

然後可以轉換成另一個方向是這樣的:

function decodeBase4(str) { 
    var i, rv = [], n = str.length; 

    for (i = 0; i < n; ++i) { 
    var b = str.charCodeAt(i) - 32; 
    rv.push(b & 3); 
    rv.push(~~(b/4) & 3); 
    rv.push(~~(b/16) & 3); 
    } 

    return rv; 
} 

這裏的the jsfiddle這似乎開展簡單的測試案例。 (請注意,最後列出的長度是3的倍數;您必須知道有多少實際值,並且最後忽略零。)

現在,這些結果字符串將是「髒「,如果你把它們放在URL中,需要URL編碼。如果每個字符僅打包2個數字,則可以使得結果字符串全部爲字母,因此您可以避免編碼損失;不過,他們當然會更長。

0

100條2位信息總共需要200位。使用base 64編碼,您需要ceil(200/log (64))= 34個字符。

A URI path segment允許79個字符不需要使用百分比編碼進行編碼。如果添加路徑段分隔符/,則您有80個字符,因此需要ceil(200/log (80))= 32個字符。這是您可以單獨使用路徑的最佳選擇。

您可以使用超過這些字符,甚至Unicode字符。但是這些需要使用百分比編碼進行編碼,因爲URI只允許包含US-ASCII。類似於ä = U + 00E4)的URI路徑實際上是/%C3%A4,只有瀏覽器將其顯示爲


下面是一個例子(從arbitrary base conversion in javascript拍攝功能):

function getValueOfDigit(digit, alphabet) 
{ 
    var pos = alphabet.indexOf(digit); 
    return pos; 
} 

function convert(src, srcAlphabet, dstAlphabet) 
{ 
    var srcBase = srcAlphabet.length; 
    var dstBase = dstAlphabet.length; 

    var wet  = src; 
    var val  = 0; 
    var mlt  = 1; 

    while (wet.length > 0) 
    { 
    var digit = wet.charAt(wet.length - 1); 
    val  += mlt * getValueOfDigit(digit, srcAlphabet); 
    wet  = wet.substring(0, wet.length - 1); 
    mlt  *= srcBase; 
    } 

    wet   = val; 
    var ret  = ""; 

    while (wet >= dstBase) 
    { 
    var digitVal = wet % dstBase; 
    var digit = dstAlphabet.charAt(digitVal); 
    ret   = digit + ret; 
    wet /= dstBase; 
    } 

    var digit = dstAlphabet.charAt(wet); 
    ret   = digit + ret; 

    return ret; 
} 

var base4Alphabet = "0123", 
    base79Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=:@", 
    base80Alphabet = base79Alphabet+"/"; 
alert(convert(getValueOfDigit("", base4Alphabet), base4Alphabet, base80Alphabet)); // "[email protected]" 
+0

使用base64編碼,每個字節可以容納3個值,不是嗎?並且64的基本2日誌是6,所以答案是34個字符,而不是70 ... – Pointy 2011-05-21 21:41:19

+0

@Pointy:Yep,log_2(64)= 6位和6位/ 2位/字符= 3個字符。 – Gumbo 2011-05-21 21:45:13

+0

恩......恩?我的觀點是,一個100位的2位數字列表可以存儲在34個字符中,因爲每個數字都可以保存(最多)三個值。 – Pointy 2011-05-21 21:48:07