添零占位 —— 快速生成N个0的六种办法


做报表的时候偶尔会遇到这种需求:

为了补齐长度,在一个数字字符串前面添加 N 个 0 占位

举个例子:

单元格需要展示 6 位数字,如 '123456'

但后端返回的数字是 123,这时候就要在前面补 0,得到 '000123',使其长度为 6

那就需要实现一个方法,基于 number 类型的参数 n,返回由 n 个 0 组成的字符串

 

以及,在众多方案中,哪一个方案的耗时最短?

 

测试模板:

// pad_start.js
 function getPlaceholder(n, mark = '0') { // ...
} function padStart(num, len) { const length = len - String(num).length; return length > 0 ? `${getPlaceholder(length)}${num}` : `${num}`; } console.time("Running"); const str = padStart(123, 10000000); console.log('字符长度:', str.length.toLocaleString()); console.timeEnd("Running");

在模板代码中,需要实现 getPlaceholder 方法来添零占位,然后统计补全千万长度的数字需要多少时间

 

方案一:for 循环

function getPlaceholder(n, mark = '0') { let str = ''; for (let i = 0; i < n; i++) { str += mark; } return str; }

作为兜底方案,for 循环可能会迟到,但从不缺席...

  

方案二:Math.pow

function getPlaceholder(n) { return Math.pow(10, n).toString().slice(1); }

由于需求是添“0”占位,可以取个巧,通过 Math.pow() 生成 10 的倍数,然后删掉首位的“1”,就得到了一串“0”

不过如果数值过大,JS 会使用科学计数法,所以这里最健壮的写法应该是:

function getPlaceholder(n) { return Math.pow(10, n).toLocaleString('zh-CN').replace(/,/g, '').slice(1); }

即便如此,由于 JS 存在数值上限 Number.MAX_VALUE,所以 Math.pow(10, 309) 的结果为 Infinity,当字符长度超过 308 时就无法使用该方案

这种方案的局限性太大,除了上面说的情况以外,如果需要使用“0”以外的占位符就用不了

所以就不对该方案测速了...

 

方案三:Number.toFixed

function getPlaceholder(n) { return (1).toFixed(n).replace('.', '').slice(1); }

如果对一个整数调用 toFixed,小数点后会用 0 来补位。基于这个特性可以很方便的生成一串“0”

和方案二类似,这种方案只适用于用“0”占位的场景

而且 toFixed 的入参只能是 0 ~ 100 的数字,无法处理超长的字符串,所以也不测速了...

 

方案四:Array.fill

function getPlaceholder(n, mark = '0') { return Array(n).fill('0').join(''); }

生成一个长度为 n 的数组,然后将元素都设为“0”,最后通过 join 拼成字符串

比较全面的方案,相对简洁,也可以自定义占位符

除了 Array.fill 之外,还可以使用其他方法,如 Array.from、Array.map

这种方案的速度就快多了,比 for 循环节省了近六成的时间

  

方案五:Array.join

function getPlaceholder(n, mark = '0') { return Array(n + 1).join(mark); }

方案四的进化版,new Array 之后会生成由 empty 构成的数组,可以直接对该数组做 join

有一点需要注意,生成的数组长度得是 n + 1,因为 join 是对数组元素的间隙做填充

相比于方案四,少了一次 Array.fill(),所以速度明显提升

 

方案六:String.padStart

ES2017 新增的方法,可以直接完成字符串的填充,参考 MDN > padStart

const num = 123; // 下面的 8 是总长度
String(num).padStart(8, "0"); // "00000123"

类似的还有 padEnd

 

对该方案的测试,需要稍微修改下测试模板的代码:

console.time("Running"); const str = String(123).padStart(10000000, "0"); console.log('字符长度:', str.length.toLocaleString()); console.timeEnd("Running");

这速度离谱吗?确实离谱!但这不是最离谱的...

 

我把字符长度从一千万逐步加到十亿,耗时居然没啥变化 ?!

可惜我翻遍了各种资料,也没查到如此高效的 String.padStart 是如何实现的...

如果有小伙伴知道原因,请一定给我留言,或者来一发传送门,拜谢~

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM