专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Javascript教程 » javascriptstring:Javascript String 思路方法效率大比拼 »正文

javascriptstring:Javascript String 思路方法效率大比拼

来源: 发布时间:星期一, 2008年12月29日 浏览:2次 评论:0
="t18">最初是通过梅子(梅花雪)有关大型串拼接效率(12)研究得到启发最近又看到never-online从trim原型看js正则表达式性能 里面有介绍正则表达式效率陷阱等问题并提出解决思路方法我向来对这些鸡毛蒜皮感兴趣也开始对大型串各种思路方法实现效率进行比较并尝试提高这些思路方法效率

1. 大型串拼接
如梅子所言使用join思路方法确实是最好实现可以根据这个思路设计StringBuilder, StringBuffer类

2. 大型串trim
其实never-online在他文章里有些说不准确地方代码也不算很精炼既然这是鸡毛蒜皮小事这些零碎东西当然要斤斤计较了
我很久以前有收集到这样些实现I:

String.prototype.trim = function{
this.replace(/(^\s+)(\s+$)/g, '');
};
为了避免正则表达式使用括号带来消耗可以写成这样II:

String.prototype.trim = function{
this.replace(/(?:^\s+)(?:\s+$)/g, '');
};
另外有套实现是这样III:

String.prototype.lTrim = function{
this.replace(/^\s+/, '');
};
String.prototype.rTrim = function{
this.replace(/\s+$/, '');
};
String.prototype.trim = function{
this.lTrim.rTrim;
};
其实也会多少有点消耗写成这样或许会快点点(开个玩笑这样写会带来些冗余代码这时候就需要基于效率(时间)、代码量(空间)和可维护性方面考量了)IV:

String.prototype.trim = function{
this.replace(/^\s+/, '').replace(/\s+$/, '');
};
后来我对正则表达式有了更多了解知道了贪婪和非贪婪匹配于是自作聪明写了这段:

String.prototype.trim = function{
this.replace(/^\s*(.*?)\s*$/, "$1"); // 两端空白贪婪匹配中间非贪婪匹配
};
我曾经为这段代码自鸣得意了好长段时间不过后来想到点号不包括换行符串中间有换行符时返回值就不正确了于是不情愿改成这样(多行模式效率也很低)V:

String.prototype.trim = function{
this.replace(/^\s*((?:.\n)*?)\s*$/, "$1");
};
谁知这样代码遇到大家伙时效率会落千丈失败

原以为String.replace思路方法比String.substr、String.sub效率低于是想只使用正则表达式获得两头(或者头)索引位置然后使用sub思路方法取出子串VI:

String.prototype.trim6 = function{
var l=this.length;
/^[\s]+/.test(this);
var s = RegExp.lastIndex;
s = -1s?0:s;
// /\s+$/.test(this);
// var e=RegExp.lastIndex;
// var e=this.$lastIndexOf(function(c){ !Char.isBlank(c);})+1;
var e=l;
(0l){ '';}
for(var i=l-1,c; i>=0; i--){
c=this.charAt(i);
(!Char.isBlank(c)){
e=i+1;
;
}
}
this.sub(s,e);
};
而最土思路方法莫过于两头都使用循环获得索引了VII:

String.prototype.trim = function{
var l=this.length, s=0, e=l;
/*for(var i=0,c; i=0; i--){
c=this.charAt(i);
(!Char.isBlank(c)){
e=i+1;
;
}
}*/
this.sub(s,this.$lastIndexOf(f)+1);
};
代码里老是for啊for大串为了节省字节而且有可能也准备再优化下循环就实现了$indexOf和$lastIndexOf两个思路方法可以传递个返回boolean值作为参数(本来还想也支持正则表达式参数想想以前扩展indexOf和lastIndexOf思路方法后效率就算了)这样就可以求得第个非空白和最后个非空白位置了

String.prototype.$indexOf = function(f){
for(var i=0,c,l=this.length; i=0; i--){
c=this.charAt(i);
(f(c)){ i;}
}
-1;
};
String.prototype.$lastIndexOf = function(f){
for(var i=this.length-1,c; i>=0; i--){
c=this.charAt(i);
(f(c)){ i;}
}
-1;
};

至于说要扩展到支持更长子串和起始索引以后有需要再说了(顺便说子串越长有优化算法可以得到更高效率)
个辅助思路方法:

var Char = {
isBlank:function(c){
// /\s/.test(c);
' 'c '\t'c '\r\n'c '\n'c '\r'c;
}
};
到了永不在线算法VIII:

String.prototype.trim = function{
var s = this.replace(/^\s+/, '');
var l=s.length, e=l;
(0l){ '';}
for(var i=l-1; i>=0; i--){
(!Char.isBlank(s.charAt(i))){
e=i+1;
;
}
}
this.sub(0,e);
};
最初这个算法让我很兴奋直觉上感觉这样效率肯定要高不过事实并不是这么简单

说到这些实现效率无法概而论区别它们效率比也大区别甚至异乎寻常

影响trim思路方法效率主要和总长度前面空白串长度后面空白串长度以及前中后比例有关详细效率对比表有时间再上这里只简要提下:

对于较小各种实现都有不错表现而对于大型则实现I, II表现最为稳定甚至可以处理超大型


3. 大型串字节长度
即双字节长度为2注意:这个提法其实也不正确Javascript是使用Unicode所有都(有可能)是双字节将汉字等转换为双字节长度主要是为了某些应用
最土思路方法还是循环遍历所有I:

String.prototype.s = function{
var l=this.length, r=l, n=0xff;
for(var i=l; i>=0; i--){
(this.charCodeAt(i)>n){
r;
}
}
r;
};
这里判断是否双字节有很多思路方法效率较高的间相差(大概)不大

种实现则看起来很轻灵寥寥几行II:

String.prototype.s = function{
this.replace(/[^\x00-\xff]/g,"xx").length;
};
多动脑子则想法愈多(也常把简单事情复杂化)我想如果可以快速取得表达式(双字节/单字节)匹配次数两值相加应该比较高效III:

String.prototype.s = function{
this.length+this.replace(/[\x00-\xff]/g,"").length;
};
IV:

String.prototype.s = function{
this.length+(this.match(/[^\x00-\xff]/g)"").length;
};
另外看到梅花雪用能提供串拼接速度也想:把串split为不想对大型串而言这split步就慢得不行

s思路方法效率:使用Javascript脚本循环大型串(I)确实远不如内置replace思路方法(II)快而使用正则表达式match思路方法(IV)又比replace思路方法(III)稍快排名第 2

整理总结:
1. replace思路方法因匹配而被替换子串愈长效率愈低
2. 根据目标选择合适实现

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: