JavaScript 在大容量數組的循環方面效率不盡人意,我曾經做過一個比對,與VBS的數組相比較,VBS的數組循環速度大致比JS要快一個數量級( http://community.csdn.net /Expert/TopicView.asp?id=4313487 )。 JS數組在一般的程式設計當中我們也不會太去注意它的效率問題:才幾十個元素的數組效率即使差點你也看不出來,但節點量一大,比如幾千、比如上萬個節點量的數組循環,那效率問題就成了首要考慮解決的問題了。大容量陣列的檢索大致有以下幾個應用:select做combo box時的快速匹配、樹的查詢、表格table排序或檢索等。
下面我來做一個測試,首先我先建立一個大容量的陣列:
<SCRIPT LANGUAGE="JavaScript">
var n = 100000; //陣列的最大容量
var a = new Array();
for(var i=0; i<n; i++)
{
a[i] = Math.random() +"";
}
</SCRIPT>
這樣我就建立了一個長度為100000 的字元型數組,然後我再檢索字串以0.9999 開始的字串,並存入另一個數組中。
<SCRIPT LANGUAGE="JavaScript">
var n = 100000; //陣列的最大容量
var a = new Array();
for(var i=0; i<n; i++)
{
a[i] = Math.random() +"";
}
var begin = new Date().getTime();
var b = new Array();
for(var i=0; i<n; i++)
{
if(a[i].indexOf("0.9999")==0)
{
b[b.length] = a[i];
}
}
document.write("陣列長度:"+ n);
document.write("<br>傳統迴圈法耗時"+ (new Date().getTime() - begin)
+" 毫秒!擷取的結果:<strong title='"+ b.join(" ")
+"'>擷取"+ b.length +" 筆記錄!</strong>");
</SCRIPT>
這步驟操作我這裡耗時都在2800毫秒左右,說明一下,這裡的循環非常簡單,只有一個if 判斷和一個賦值操作,非常簡單,若這裡的判斷稍微複雜一些那它的耗時將是數量級的增大。那麼對於這種問題有什麼好的優化方案嗎?答案當然是有的,否則我開這個貼文說的全是費話了。但是對於這個問題不能再使用我們的傳統思維來優化,因為在傳統的思維裡已經找不出再好的寫法了。
解決的方案是:先把陣列join()成一個大字串,然後用正規表示式對這個大字串進行比對檢索。這個方法算是我的個人獨創吧,在我寫樹的過程中想出的歪招,不過效率真的不賴。關於join()的效率我已經開貼討論過了( http://blog.csdn.net/meizz/archive/2005/12/14/552260.aspx JavaScript極速狂飆:組合拼接字串的效率)。這個最佳化方案需要有一定的正規表示式功底。
<input id="count" value="50000" size="7" maxlength="6">
<input type="button" value="數組初始華" onclick="txt.innerHTML = array_init()"><br>
<input type="button" value="傳統迴圈" onclick="txt.innerHTML += method_for()">
<input type="button" value="正規符合" onclick="txt.innerHTML += method_regexp()">
<div id="txt"></div>
<SCRIPT LANGUAGE="JavaScript">
var txt = document.getElementById("txt");
var a = new Array();
function array_init()
{
var n = parseInt(document.getElementById("count").value);
a.length = 0;
for(var i=0; i<n; i++)
{
a[i] = Math.random() +"";
}
return "數組長度:"+ n;
}
function method_for()
{
var n = a.length;
var begin = new Date().getTime();
var b = new Array();
for(var i=0; i<n; i++)
{
if(a[i].indexOf("0.9999")==0)
{
b[b.length] = a[i];
}
}
return ("<br>傳統迴圈法耗時"+ (new Date().getTime() - begin)
+" 毫秒!擷取的結果:<strong title='"+ b.join(" ")
+"'>擷取"+ b.length +" 筆記錄!</strong>");
}
function method_regexp()
{
var begin = new Date().getTime();
var b = new Array();
var s = a.join("x0f");
var r = new RegExp().compile("0\.9999\d+", "g");
b = s.match(r); s = "";
return ("<br>正規匹配法耗時"+ (new Date().getTime() - begin)
+" 毫秒!擷取的結果:<strong title='"+ b.join(" ")
+"'>擷取"+ b.length +" 筆記錄!</strong>");
}
</SCRIPT>
大家可以測試一下,上面兩種方法之間的效率到底相差多少!代碼是死的,人是活的,換一種思維換一種模式,效率將大相逕庭。
這一招我是花了好多腦筋才想出來的招,真有點捨不得放出來,現在就拿它恭賀大家2006新的一年的開始吧。