2011-03-20 12 views
6

該JavaScript函數接受一組數字(範圍在0-255之間)並轉換爲base64編碼的字符串,然後打破long如果需要的話:將字節值數組轉換爲base64編碼的字符串,並打破長長的線,Javascript(代碼高爾夫)

function encode(data) 
{ 
    var str = ""; 
    for (var i = 0; i < data.length; i++) 
    str += String.fromCharCode(data[i]); 

    return btoa(str).split(/(.{75})/).join("\n").replace(/\n+/g, "\n").trim(); 
} 

你能用少代碼做同樣的事嗎?你能做到這一點,所以它運行得更快嗎?可移植性沒有對象,如果你想使用全新的語言特性,但必須使用JavaScript。

+0

在什麼瀏覽器(S)跑得快?據我所知,'btoa'只支持Gecko和WebKit瀏覽器。 – Gabe 2011-03-20 04:41:05

+0

碰巧,這是一個非常小的Firefox擴展,但如果你有一個聰明的方法來使用其他瀏覽器的JS來完成它,我也很樂意看到它。 – zwol 2011-03-20 17:13:03

+0

ahem ... http://codegolf.stackexchange.com/ – jessegavin 2011-03-20 17:50:06

回答

13

我有另外一個條目:

function encode(data) 
{ 
    var str = String.fromCharCode.apply(null,data); 
    return btoa(str).replace(/.{76}(?=.)/g,'$&\n'); 
} 

縮小,88個字符:

function e(d){return btoa(String.fromCharCode.apply(d,d)).replace(/.{76}(?=.)/g,'$&\n')} 

或者,如果你想尾隨換行,85個字符:

function e(d){return btoa(String.fromCharCode.apply(d,d)).replace(/.{1,76}/g,'$&\n')} 
+1

哦,非常好!雖然我不是100%確定使用'apply'。對於任何函數(無論如何,Firefox都是這樣)有2 ** 19個參數的限制,我認爲它可能不得不做更多的工作,將數組解壓縮到參數區域。儘管如此,我並不認爲我的陣列會變得很長,而且它的短小很好。 – zwol 2011-03-20 19:06:56

+0

我剛纔測試了它(在Firebug中),它在這裏處理了大約12 * 2 ** 20個數字。這甚至不是一個硬性限制,它只是報告腳本堆棧空間配額已用盡。 – Anomie 2011-03-20 19:43:08

+0

需要多長時間?你能用大字節數組來計算我們的各種方法嗎? – Gabe 2011-03-20 20:22:24

2

在Firefox 3.6.13:

function encode(data) 
{ 
    var str = data.reduce(function(a,b){ return a+String.fromCharCode(b) },''); 
    return btoa(str).replace(/.{76}(?=.)/g,'$&\n'); 
} 
+0

你需要那裏的「trim」嗎? – Gabe 2011-03-20 17:20:17

+0

@Gabe:當base64編碼的字符串是行長度的精確倍數時,我將它放入以避免返回的字符串有尾隨換行符,否則就沒有換行符。但是在回覆你時,我認爲「Firefox的javascript正則表達式引擎是否支持零寬度積極預測?」。它確實!編輯。 – Anomie 2011-03-20 17:28:57

+0

哦,這裏的對象是最小字符嗎?如果你想讓每個輸出都有一個尾隨的換行符(把正則表達式改成'/。{1,76}/g'),這可以縮小到116個字符,或者113個。 – Anomie 2011-03-20 18:06:50

1

我沒有火狐好用,所以我不能嘗試一下,但是從一般的字符串處理角度看,它看起來你有一些空間改善。你正在做的是,對於每個字節,創建一個比前一個字符長一個字符的新字符串。這是一個O(N^2)操作。有削減N A幾種方法讓你的算法在接近線性的時間運行:

  1. 樹立字符串長度57(這將產生一個76字符的Base64結果),然後執行一個btoa並將結果字符串添加到輸出中

  2. 就像#1一樣,只建立一行數組並且調用join來創建最終的輸出字符串。

  3. 使用map創建1個字符的字符串數組,然後調用join

下面是每個方法的一些未經測試的代碼:

function encode(data) 
{ 
    var output = ""; 
    var str = ""; 
    for (var i = 0; i < data.length; i++) 
    { 
    str += String.fromCharCode(data[i]); 
    // the "&& i != data.length - 1" clause 
    // keeps the extra \n off the end of the output 
    // when the last line is exactly 76 characters 
    if (str.length == 57 && i != data.length - 1) 
    { 
     output += btoa(str) + "\n"; 
     str = ""; 
    } 
    } 
    return output + btoa(str); 
} 

function encode(data) 
{ 
    var output = []; 
    var str = ""; 
    for (var i = 0; i < data.length; i++) 
    { 
    str += String.fromCharCode(data[i]); 
    if (str.length == 57) 
    { 
     output[output.length] = btoa(str); 
     str = ""; 
    } 
    } 
    if (str != "") 
    output[output.length] = btoa(str); 
    return output.join("\n"); 
} 

function encode(data) 
{ 
    var str = data.map(function (d) { return String.fromCharCode(d) }).join(""); 
    return btoa(str).replace(/.{76}(?=.)/g,'$&\n'); 
} 

而這裏的最後一個,精縮(116個字):

function e(b){return btoa(b.map(function(d){return 
String.fromCharCode(d)}).join("")).replace(/.{76}(?=.)/g,'$&\n')} 
+0

需要閉包,因爲映射通過3個參數(數組元素,索引和數組對象)調用其函數,並且String.fromCharCode可以將多個代碼點作爲參數來返回多個字符的字符串。巧合的是,我在你發佈之前記得這一點,並意識到我可以利用這一事實。 – Anomie 2011-03-20 18:16:12

+0

我喜歡一次分塊57個字節的想法,以提供給'btoa'。 – zwol 2011-03-20 19:13:38

相關問題