添零占位 —— 快速生成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