原创 JavaScript极速狂飙:大容量字符型数组的快速检索收藏

新一篇: 用函数式编程技术编写优美的 JavaScript | 旧一篇: flash 8 maelstrom基础教程

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("&#13;")
    +"'>检索到 "+ 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("&#13;")
    +"'>检索到 "+ 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("&#13;")
    +"'>检索到 "+ b.length +" 个记录!</strong>");
}
</SCRIPT>

    大家可以测试一下,上面两种方法之间的效率到底相差多少!代码是死的,人是活的,换一种思维换一种模式,效率将大相径庭。

    这一招我是花了好多脑筋才想出来的招,真有点舍不得放出来,现在就拿它恭贺大家2006新的一年的开始吧。


 

发表于 @ 2006年07月05日 03:43:00|评论(loading...)|编辑

新一篇: 用函数式编程技术编写优美的 JavaScript | 旧一篇: flash 8 maelstrom基础教程

评论

#路过 发表于2006-07-05 10:33:00  IP: 218.82.100.*
试过了,效率的确提升了不少,但是好像我用火狐和用ie的结果正好已经反过来了。
应该是浏览器解析的原因吗?能不能再解释下呢?
#tony 发表于2006-07-05 11:24:00  IP: 60.12.8.*
你所说的效率提高只是因为用了正则吗?你又如何知道正则是如何实现的呢?我觉得你弄清楚到底是谁在影响效率,只是恰好凑了一种稍微快点的方法而已
#网络隐士 发表于2006-07-05 13:12:00  IP: 10.240.48.*
楼主的数据结构有问题,设计好一点无须如此慢
#tiewen 发表于2006-07-05 18:25:00  IP: 220.248.72.*
楼主解释了 解释型语言提高运行速度的一个方法:
把多次解释转变为1次或较少次的解释。

1、尽量减少循环,乃至替换循环
2、循环中尽可能少些操作
3、在涉及数组排序,字串匹配等时,尽量使用js核心类/函数
Array.sort是应用程序级的速度,而自己写的if(a==b)是解释级的。
不久前看到帖子说用table排序时用appendChild比用swapNode快5倍什么,其实真正将速度大规模提升的是Array.sort的使用
#醉梦流仙 发表于2006-07-06 17:31:00  IP: 210.21.33.*
tony 和tiewen 说得对..
其实这个提高不在于join成大字符串.而在于正则.或者换个说法..tiewen所说.用核心函数
#CSDN BLOG编辑 发表于2006-07-07 10:50:00  IP: 218.247.0.*
迪网友,经过CSDN Blog专家顾问团的合议,您的文章:"JavaScript极速狂飙:大容量字符型数组的快速检索",成为7月4日的“每日一帖”!请参考下面的提示和我们联系领取奖品事宜,谢谢你向广大CSDN网友分享你的原创文章。

提示:
1.评选时间为周一至周五!
2.请您及时查看和关注您的个人Blog,我们会以评论的形式告诉您获奖的信息。
3.本次活动奖品是由第二书店提供的100个D币,请访问第二书店(www.dearbook.com.cn)激活您的D币帐号;激活后请将您[Dearbook的注册邮件]/[Blog的帐号]//[获奖文章名称]/[获奖日期]回复邮件给我们的编辑gaocao(AT)csdn.net;
4.请各位网友及时查收您的D币帐号,有问题及时和我们联系,或者在本栏目评论。
5.[每日一帖]不断更新中…… 明天将评选出今天的每日一帖
6.详细请参考:http://blog.csdn.net/todaypost/
#hong1 发表于2006-07-07 18:34:00  IP: 218.249.190.*
我在opera里面测试的速度是差不多的!!
这可能是浏览器对js的解释方法不一样吧!
#呵呵 发表于2006-07-08 16:26:00  IP: 58.20.32.*
推荐一个网络赚钱的方法,绝对真实,http://www.ifreeter.com/nid 谢谢支持.
#PINK 发表于2006-07-15 12:46:00  IP: 222.67.173.*
CONECT WITH ME
KE
发表评论  


登录
Csdn Blog version 3.1a
Copyright © Tino