zoukankan      html  css  js  c++  java
  • 在js中做数字字符串加0补位,效率分析

    分类: Jquery/YUI/ExtJs

    通常遇到的一个问题是日期的“1976-02-03 HH:mm:ss”这种格式 ,我的比较简单的处理方法是这样:

    function formatDate(d) {
      var D=['00','01','02','03','04','05','06','07','08','09']
      with (d || new Date) return [
        [getFullYear(), D[getMonth()+1]||getMonth()+1, D[getDate()]||getDate()].join('-'),
        [D[getHours()]||getHours(), D[getMinutes()]||getMinutes(), D[getSeconds()]||getSeconds()].join(':')
      ].join(' ');
    }

    这种方法是逻辑比较简单的,而且规则也简单。除了with(d||new Date)的使用之外,也算不上什么技巧。但是,如果用这种方法来做数字字符串补0,那么结果显然不妙。51js的月影提供了另一个方案:

    function pad(num, n) {
      return Array(n>num?(n-(''+num).length+1):0).join(0)+num;
    }

    调用示例如下:

    pad(100, 4);  // 输出:0100

    月影在这里分析了其中的技巧,以及代码长短与效率上的平衡:

    http://hi.baidu.com/akira_cn/blog/item/90ba2a8b07c867dafc1f1045.html

    最后月影推荐的是“质朴长存法”:

    /* 质朴长存法  by lifesinger */
    function pad(num, n) {
        var len = num.toString().length;
        while(len < n) {
            num = "0" + num;
            len++;
        }
        return num;
    }

    这个在“没事就射鸟”同学的博客里做了分析:

    http://lifesinger.org/blog/2009/08/the-harm-of-tricky-code/

    月同学有一件事是没有做的,就是没说明“为什么那个短代码的效率更低?”。

    答案是“表面看来,用array.join来替代循环是高效的,但忘掉了一个数组创建的开销”。对此有没有法子呢?我有过另一个解决的思路。如下:

    /* 查表法(不完善)  by aimingoo */
    pad = function(tbl) {
      return function(num, n) {
        return (((tbl[n = n-num.toString().length]) || (tbl[n] = Array(n).join(0))) + num);
      }
    }([]);

    这个路子跟前面的formatDate()是一样的,只不是formatDate()里的表是一个确定的数组,而这里的数组则是动态生成,然后缓存 在tbl[]里面。这个缓存的tbl[]数组是使用一个函数调用参数的形式,保持在最终的pad()函数的上层闭包里面。为了让上面的这个过程清晰一点, 我重排代码格式如下:

    pad = function(tbl) {
      return function(num, n) {
        return (
          ((tbl[n = n-num.toString().length]) ||
           (tbl[n] = Array(n).join(0))) +
          num
        );
      }
    }([]);

    好的。到这里,先别急,还有两个问题要解决。其一,当不需要补0时,上述的tbl[0]返回空值,所以会进入到“||”运算的第二个分支,因此导致 Array()重算一次,也就是说“不补0的情况效率其实最低”。其二,当num长度大于n时,也就变成了“补负数个零”。“补负数个零”显然不行,一般 对此处理成“不需要补零”,于是又回到了第一个问题。

    这两个问题可以一次解决,其实就是多一次判断:

    /* 查表法(完善版本)  by aimingoo */
    pad = function(tbl) {
      return function(num, n) {
        return (0 >= (n = n-num.toString().length)) ? num : (tbl[n] || (tbl[n] = Array(n+1).join(0))) + num;
      }
    }([]);

    当然,也可以象前面一样整理一下这个代码格式。或者,采用一个完全不用“(函数式语言的)连续运算等技巧”的版本:

    /* 查表法(过程式版本)  by aimingoo */
    pad = function() {
      var tbl = [];

      return function(num, n) {
        var len = n-num.toString().length;
        if (len <= 0) return num;
        if (!tbl[len]) tbl[len] = (new Array(len+1)).join('0');
        return tbl[len] + num;
      }
    }();

    算法永远都是如此,要不是时间换空间,要不就是空间换时间。射雕同学的“质朴长存法”是时间换空间的方法,而这里的查表法则是空间换时间的方案。这 个函数会在tbl中持续一个字符串数组,如果num是非常经常变化的,那么效率也不会有太大提升——对于过于频繁变化的系统,缓存就意义不大了。其实逻辑 都差不多,月影同学只是少走了一步而已。


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/aimingoo/archive/2009/08/28/4492592.aspx

  • 相关阅读:
    遇见Javascript类型数组
    编译Android常用命令
    V4L2驱动视频开发要点
    Windows Phone开发(27):隔离存储A
    Ubuntu10.04下Android开发环境搭建
    V4L2开发要点
    使用 php Header 报错的一个原因
    Windows Phone开发(28):隔离存储B
    用HTML5 Audio API开发游戏音乐
    php备份数据库类分享
  • 原文地址:https://www.cnblogs.com/wangcq/p/3877716.html
Copyright © 2011-2022 走看看