在JavaScript中如何用前导零填充数字

703
在JavaScript中,我需要填充内容。
例如,如果我有数字9,它将变为“0009”。 如果我有一个数字10,它将变为“0010”。 请注意它将始终包含四个数字。
一种方法是减去数字减4以获取我需要放置的0的数量。
是否有更加简洁的方法来做到这一点?

293
("0000" + num).substr(-4,4); 这行代码可以简洁地实现将数字转换成四位数的字符串形式。 - slartibartfast
244
据我所知,("0000" + num).slice(-4) 可以在任何地方使用,它会将数字转化为长度为4的字符串格式。 - Rast
14
如果你已经在使用lodash:https://lodash.com/docs#padLeft - mpen
36
('000' + num).slice(-4)就足够了 ;) - Martin Schneider
93
ES2017: String(n).padStart(4, '0') - bpceee
显示剩余10条评论
9个回答

989

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;
}

如果你用一个数字初始化数组,它将创建一个长度设置为该值的数组,以便该数组看起来包含那么多个未定义的元素。尽管某些数组实例方法跳过没有值的数组元素,但.join()不会,至少不完全;它将它们视为其值为空字符串。因此,在每个数组元素之间,你会得到零字符(或者无论“z”是什么)的副本;这就是为什么其中有一个+ 1的原因。

例如用法:

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

pad(10, 4, '-'); // --10

4
在程序员看来,分配空间是实现细节,是不可见的(我知道的开放实现如Rhino、V8、SM、JSC都没有这样做)。任何分配内存并暴露属性的实现都违反了EcmaScript规范,在“数组构造函数15.4.2.2”下已经非常明确地说明了这一点。虽然这并不是一个大问题,答案本身很好,但如果你能修复这个细节,那就更好了。 - Benjamin Gruenbaum
8
谢谢您的回答,但是像“n”和“z”这样的变量并不直观,不清楚它们的作用是什么。 - DLeh
2
@DLeh "n" 是需要填充的数字,而 "z" 是(默认情况下)用于填充的零或其他字符。 - Pointy
12
你真的需要一个数组吗?function pad(n, width, z) { while(n.length<width) n = '' + z + n; return n;} - Paolo
22
简洁、紧凑、可扩展。function pad(n, width=3, z=0) {return (String(z).repeat(width) + String(n)).slice(String(n).length)} - Gui LeFlea
显示剩余11条评论

278
function padToFour(number) {
  if (number<=9999) { number = ("000"+number).slice(-4); }
  return number;
}

像这样吗?

额外附加的单行ES6版本可能有些难以理解,但是更简洁:

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

ES6主要特性:

  • let是块级作用域变量(与var的函数级作用域不同)
  • =>是一个箭头函数,可以替换function,并在其参数之前加上
  • 如果箭头函数只有一个参数,可以省略括号(因此number =>
  • 如果箭头函数主体只有一行以return开头的语句,可以省略大括号和return关键字,并直接使用该表达式
  • 为了将函数主体缩减为单行,我使用了三元表达式

1
这很简单,但并不那么新颖;最近我也做了类似的事情,发现了这种方法在线上。 - Robin Whittleton
5
只减少了一个投票,因为这不是一种模块化的方法(仅适用于4位数)。当然,这是对特定问题的具体回答,但包括长度选项会更好(就像其他答案一样)。 - doubleJ
9
实际上,@JorgeOrpinel,它不会被截断。if语句使切片操作仅对四位或更少位数的数字进行操作。五位数至少具有10000的值,而10000不符合<=9999的条件。 - Luke Griffiths
1
它看起来很流畅,但请注意,此函数将根据其输入值的不同而返回不同类型:对于小于1000的数字,返回Number,对于更大的数字,则返回String。这种对类型的轻率处理是 JavaScript 程序中无数错误的源头。我建议还将“else”分支的值转换为String... : "" + number - Tad Lispy
6
我认为自从使用sprintf (padToFour, "%04d", number);的时代以来,我们的进步倒退了。 - gregn3
显示剩余7条评论

248

尝试:

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"

2
为了完整起见,您应该从最终字符串中取出最后的 length 个字符,以处理 padString 大于一个符号的情况。 - DCoder
6
你目前的做法是"5".lpad("--", 4)会产生"----5"而不是 "---5"。 - DCoder
11
将String原型扩展像其他内置对象一样并不推荐。 - user212328
10
感谢指出 ES8 的解决方案。这里有一个简单的 polyfill,详情请见:http://2ality.com/2015/11/string-padding.html。 - Marco Luglio
6
ES8解决方案应该是当今的最佳答案。您应该将其放在您的答案顶部。 - Iulius Curt
显示剩余3条评论

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"

不够美观,但是有效。


@doubleJ 的和我的实际上非常相似,如果不是完全一样的话,只是他的有一个特性,就是可以用除了 0 以外的其他东西来填充。你可以像使用我的那样使用他的 pad(15, 3) - Peter C
写了一个类似的答案,我首先将num转换为str,然后使用return (Array(Math.max(5-str.length, 0)).join("0") + str);,如果其他问题被删除,就放弃这个答案。 - ajax333221
2
为了处理负数,首先使用该数字的绝对值,然后在结果末尾添加一个负号(“-”)来表示这是一个负数。其中,“value”是Math.abs(number),代码如下:(number < 0 ? '-' : '') + Array(Math.max(digits - String(value).length + 1, 0)).join(0) + value - Neil Monroe
我非常喜欢这个解决方案@NeilMonroe,但您能否为我们分解一下呢?作为评论,它不太易读。 :) - J.M. Janzen

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);
}

2
很想知道为什么这个没有得到赞。看起来是最合乎逻辑和完整的解决方案。示例用法var v=2; v.padZero(4); v.padZero(4,'+');产生'0002' '+++2' - rob
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Mikebert4
2
因为这是一个过于具体的解决方案,所以以下代码是更清晰的解决方案。如果误用了pad,则会产生较少的效果,并且只会添加不影响可读性或可访问性的空格。 String.prototype.lpad = function(len, c){ var s= '', c= c || ' ', len= (len || 2)-this.length; while(s.length - MrMesees

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 );
}

这段代码执行2个操作:

  1. 如果数字大于指定大小,它将返回该数字。
  2. 在使用 ~~num 的位置上使用 Math.floor(num) 将支持更大的数字。

2
pad(1111111111111, 10)返回714581447 - Serkan Yersen
2
这是因为在我的原始解决方案中,数字太大了,无法使用该方法(~~num)。为了支持更大的数字,我添加了一个使用Math.floor()函数的新版本。除此之外,您提供的数字超过了指定的大小,因此我添加了对该情况的检查。 - Robert Messerle
这个解决方案并不实用,因为1)只适用于小尺寸的值,2)无法处理小数位:例如 pad(0.3333,10) = '0000000000'。 - Ron Wertlen

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位填充),因此它不是通用的。


2
这个代码还够简洁吗?((x < 10) ? '000' : (x < 100) ? '00' : (x < 1000) ? '0' : '')+(+x) - AlexChaffee
可能吧,AlexChaffee。 :) - xxbbcc
@Hafthor,你是认真建议还是开玩笑发的? - xxbbcc

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;
}

new Array(needed + 1).join('0') 怎么样,而不是使用那个昂贵的指数? :-) - Pointy
2
请注意,这仅适用于长度小于某个大小的情况,在数字转换为科学计数法之前。Pointy的数组用法通常更有效。(@Pointy: 因为这只是为了好玩 :) - Phrogz
1
是的,我知道。那就像是 Array 构造函数唯一合法的用途,所以它值得被提及 :-) - Pointy

2
既然您提到它将始终具有长度为4,我将不会进行任何错误检查以使其更加流畅。;)
function pad(input) {
    var BASE = "0000";
    return input ? BASE.substr(0, 4 - Math.ceil(input / 10)) + input : BASE;
}

想法:只需用提供的数字替换“0000”...问题在于,如果输入为0,则需要硬编码以返回“0000”。LOL。
这应该足够简洁。
JSFiddler: http://jsfiddle.net/Up5Cr/

这里是一些随机输出,证明它并不像你想象的那么流畅... 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 80 - Rheijn
不是完美,但我喜欢这个想法。有人在跳出常规思维 :) ... 或许可以用4-`${input}`.length()替换4-Math.ceil(...)部分。 - bvdb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接