在JavaScript中用前导零填充一个数字

回答 9 浏览 71.8万 2012-04-09

在JavaScript中,我需要有padding。

例如,如果我有数字9,它将是 "0009"。如果我有一个数字,例如10,它将是 "0010"。请注意,它总是包含四个数字。

有一种方法是用数字减去4,得到我需要放的0的数量。

是否有更巧妙的方法来做这件事呢?

Nate Pet 提问于2012-04-09
("0000" + num).substr(-4,4); //短小精悍。slartibartfast 2014-03-04
("0000"+num).slice(-4)在任何地方都能工作,AFAIKRast 2014-12-30
如果你已经在使用lodash:lodash.com/docs#padLeftmpen 2015-07-13
('000' + num).slice(-4)就够了;)Martin Schneider 2017-04-13
ES2017年:String(n).padStart(4, '0')bpceee 2018-03-14
9 个回答
#1楼
得票数 929

ES2017年的更新

你可以使用内置的String.prototype.padStart(),这也是一个很好的方法。

n = 9;
String(n).padStart(4, '0'); // '0009'

n = 10;
String(n).padStart(4, '0'); // '0010'

到目前为止,没有很多"华而不实"的事情发生:

function pad(n, width, z) {
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

当你用一个数字初始化一个数组时,它会创建一个数组,并将length设置为该值,这样数组看起来就包含了那么多undefined元素。尽管一些数组实例方法跳过了没有值的数组元素,但.join()没有,或者至少没有完全跳过;它把它们当作其值是空字符串。因此,你会在每个数组元素之间得到一个零字符的拷贝(或者不管"z"是什么);这就是为什么那里有一个+ 1

用法举例:

pad(10, 4);      // 0010
pad(9, 4);       // 0009
pad(123, 4);     // 0123

pad(10, 4, '-'); // --10
Pointy 提问于2012-04-09
Patrick McElhaney 修改于2021-05-24
"当你用一个数字初始化一个数组时,它会创建一个有那么多未定义元素的数组。 "-我认为这不正确。它只是设置了length属性,并加入了length次迭代。对未定义属性的访问总是返回undefined。参见"5" in Array(5)"0" in [1]Benjamin Gruenbaum 2014-07-24
@Pointy分配空间是程序员看不到的实现细节(我所知道的开放的实现都没有这样做(Rhino、V8、SM、JSC),任何分配内存暴露属性的实现都违反了EcmaScript规范,该规范对此有明确规定(在"阵列构造器15.4.2.2"下)。这不是什么大问题,而且答案也很好,如果你能修复这个细节就更好了。Benjamin Gruenbaum 2014-07-24
谢谢你的回答,但像"n"和"z"这样的变量并不直观,不知道它们在做什么。DLeh 2015-05-21
你真的需要一个阵列吗?function pad(n, width, z) { while(n.length<width) n = '' + z + n; return n;}Paolo 2016-02-18
聪明"、紧凑、可扩展。function pad(n, width=3, z=0) {return (String(z).repeat(width) + String(n)).slice(String(n).length)}Gui LeFlea 2016-06-01
#2楼
得票数 275
function padToFour(number) {
  if (number<=9999) { number = ("000"+number).slice(-4); }
  return number;
}

诸如此类的问题?

额外的难以理解但更流畅的单行 ES6 版本:

let padToFour = number => number <= 9999 ? `000${number}`.slice(-4) : number;

ES6isms:

  • let是一个块作用域的变量(相对于var的功能作用域)。
  • =>是一个箭头函数,除其他外,它可以取代function,并以其参数为前缀。
  • 如果一个箭头函数只取一个参数,你可以省略括号(因此,number =>)。
  • 如果一个箭头函数体有一个以return开头的单行,你可以省略大括号和return关键字,只需使用表达式即可。
  • 为了将函数体缩减到一行,我作弊使用了一个三元表达式
Robin Whittleton 提问于2012-04-09
Pang 修改于2022-08-02
这很简单,但并不那么新奇;我最近要做类似的事情,在网上找到了这种方法。Robin Whittleton 2012-04-09
只拿掉了一票,因为这不是一个模块化的方法(只适用于4位数)。当然,这是一个特定问题的具体答案,但包括一个长度选项会更好(像其他答案一样)。doubleJ 2013-11-04
我喜欢slice的用法。然而,正如@doubleJ所提到的,请注意这种方法的一个局限性是会将数字截断到最后4位。Jorge Orpinel Pérez 2014-03-23
实际上 @JorgeOrpinel 它不会截断。if语句使切片操作只对四位数或更少的数字进行操作。一个五位数的数字至少有10000的值,这不是<=9999。Luke Griffiths 2014-06-26
我认为,自从sprintf (padToFour, "%04d", number);的时代以来,我们已经取得了倒退的进展。gregn3 2019-08-07
#3楼
得票数 247

试试吧:

String.prototype.lpad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = padString + str;
    return str;
}

现在测试一下:

var str = "5";
alert(str.lpad("0", 4)); //result "0005"
var str = "10"; // note this is string type
alert(str.lpad("0", 4)); //result "0010"

DEMO


ECMAScript 2017中,我们有新的方法padStartpadEnd,它的语法如下。

"string".padStart(targetLength [,padString]):

因此,现在我们可以使用

const str = "5";
str.padStart(4, "0"); // "0005"
xkeshav 提问于2012-04-09
xkeshav 修改于2020-12-21
为了完整起见,你应该从最后的字符串中取出最后的length个字符,以处理padString是一个以上的符号的情况。DCoder 2012-04-09
你的做法是,"5".lpad("--", 4)会产生"----5",而不是"---5"。DCoder 2012-04-09
不建议将String原型扩展为任何其他的内置式。user212328 2014-12-13
+1,指出了ES8的解决方案。这里有一个简单的polyfill描述:2ality.com/2015/11/string-padding.htmlMarco Luglio 2018-01-29
ES8解决方案应该是现在的答案。你应该把它放在你答案的最前面。Iulius Curt 2019-11-26
#4楼
得票数 71

有趣的是,我最近不得不这样做了。

function padDigits(number, digits) {
    return Array(Math.max(digits - String(number).length + 1, 0)).join(0) + number;
}

像这样使用:

padDigits(9, 4);  // "0009"
padDigits(10, 4); // "0010"
padDigits(15000, 4); // "15000"

不是很美,但很有效。

Peter C 提问于2012-04-09
@doubleJ Pointy 和我的实际上非常相似,即使不完全相同,除了他具有能够填充 0 以外的其他内容的功能。您可以像使用我的方法一样使用他的pad(15, 3)Peter C 2013-11-06
写了一个类似的答案,我先把num变成str,然后用return (Array(Math.max(5-str.length, 0)).join("0") + str);,只是把这个丢掉,以防其他Q被删除了ajax333221 2014-01-17
要处理负数,使用数字的绝对值,然后在最终结果上加上一个负号('-')。(number < 0 ? '-' : '') + Array(Math.max(digits - String(value).length + 1, 0)).join(0) + value其中'值'为Math.abs(number)Neil Monroe 2015-02-20
我非常喜欢这个解决方案@NeilMonroe,但你能不能为我们分解一下?作为一个评论,它的可读性不强。)J.M. Janzen 2020-06-01
#5楼
得票数 25

你确实说过你有一个号码--

String.prototype.padZero= function(len, c){
    var s= '', c= c || '0', len= (len || 2)-this.length;
    while(s.length<len) s+= c;
    return s+this;
}
Number.prototype.padZero= function(len, c){
    return String(this).padZero(len,c);
}
kennebec 提问于2012-04-09
我很想知道为什么这没有得到支持。这似乎是最符合逻辑和最完整的解决方案。示例用法 var v=2; v.padZero(4); v.padZero(4,'+'); 产生'0002' '++2';rob 2013-12-15
我一直在寻找用前导零填充,这是我选择的解决方案。应该会有更多的人支持。Mikebert4 2015-10-16
因为这是个太特殊的解决方案...``` String.prototype.lpad = function(len, c){ var s= '', c= c || ' ', len= (len || 2)-this.length; while(s.length<len) s+= c; return s+this; }Number.prototype.lpad = function(len, c){ return String(this).lpad(len, c); }Number.prototype.lpadZero = function(len) { return this.lpad(len,'0'); }```是一个更清晰的解决方案,因为它是可预测的;如果错误地使用了pad,产生的效果会更少,它只是增加了空格,不影响可读性和可访问性。MrMesees 2015-11-07
#6楼
得票数 14

你可以做这样的事情:

function pad ( num, size ) {
  return ( Math.pow( 10, size ) + ~~num ).toString().substring( 1 );
}

编辑:这只是一个函数的基本想法,但为了增加对更大的数字(以及无效输入)的支持,这可能会更好:

function pad ( num, size ) {
  if (num.toString().length >= size) return num;
  return ( Math.pow( 10, size ) + Math.floor(num) ).toString().substring( 1 );
}

这有两方面的作用:

  1. 如果数字大于指定的大小,它将简单地返回这个数字。
  2. 使用Math.floor(num)来代替~~num将支持更大的数字。
Robert Messerle 提问于2012-04-09
Robert Messerle 修改于2014-04-01
pad(1111111111111, 10)返回714581447Serkan Yersen 2014-03-31
这是由于这个数字对于我原来的解决方案(~~num)中使用的方法来说太大。为了支持更大的数字,我添加了一个新版本的这个函数,使用Math.floor()。除此之外,你提供的数字比你指定的大小要大,所以我为这种情况增加了一个检查。Robert Messerle 2014-04-01
这个解决方案并不实用,因为1)只适用于小的尺寸值,2)不能处理小数位:例如,pad(0.3333,10) = '00000000';Ron Wertlen 2015-08-13
#7楼
得票数 2

这其实并不 "聪明",但做整数运算比为每个填充物0做字符串连接要快。

function ZeroPadNumber ( nValue )
{
    if ( nValue < 10 )
    {
        return ( '000' + nValue.toString () );
    }
    else if ( nValue < 100 )
    {
        return ( '00' + nValue.toString () );
    }
    else if ( nValue < 1000 )
    {
        return ( '0' + nValue.toString () );
    }
    else
    {
        return ( nValue );
    }
}

这个函数也是根据你的特殊需要硬编码的(4位数的填充),所以它不是通用的。

xxbbcc 提问于2012-04-09
这很滑稽吗?((x < 10) ? '000' : (x < 100) ? '00' : (x < 1000) ? '0' : '')+(+x)AlexChaffee 2018-03-20
@Alex Chaffee 可能是这样的。)xxbbcc 2018-03-20
@Hafthor 你是作为一个严肃的建议发布的,还是只是一个玩笑?xxbbcc 2019-01-29
#8楼
得票数 2

为了好玩,不使用循环来创造额外的零,而是使用循环:

function zeroPad(n,length){
  var s=n+"",needed=length-s.length;
  if (needed>0) s=(Math.pow(10,needed)+"").slice(1)+s;
  return s;
}
Phrogz 提问于2012-04-09
new Array(needed + 1).join('0')来代替那昂贵的指数运算如何? :-)Pointy 2012-04-09
请注意,这只对长度低于一定大小的情况有效,在数字转换为科学符号之前。Pointy's Array的用法在一般情况下更有效。(@Pointy: 因为这只是为了好玩 :)Phrogz 2012-04-09
是的,我知道。这是对数组构造函数的唯一合法使用,所以它值得一谈。)Pointy 2012-04-09
#9楼
得票数 2

既然你提到它的长度总是为4,那么我就不会做任何错误检查来使其变得更加灵活。)

function pad(input) {
    var BASE = "0000";
    return input ? BASE.substr(0, 4 - Math.ceil(input / 10)) + input : BASE;
}

主意:简单地用所提供的数字替换'0000'......这样做的问题是,如果input是0,我需要用硬编码来返回'0000'。大笑。

这应该是够滑稽的了。

JSFiddler:http://jsfiddle.net/Up5Cr/

DashK 提问于2012-04-09
Peter Mortensen 修改于2017-04-26
下面是一些随机输出,证明这并不像你想象的那样华而不实...... bundle.js:81 023 bundle.js:81 024 bundle.js:81 025 bundle.js:81 026 bundle.js:81 027 bundle.js:81 028 bundle.js:81 029 bundle.js:81 030 ......bundle.js:81 80Rheijn 2018-05-25
不完美,但我喜欢这个想法。有人跳出框框思考问题 :)...也许可以把4-Math.ceil(...)部分改为4-`${input}`.length()bvdb 2019-01-20