535

In JavaScript, I need to have padding.

For example, if I have the number 9, it will be "0009". If I have a number of say 10, it will be "0010". Notice how it will always contain four digits.

One way to do this would be to subtract the number minus 4 to get the number of 0s I need to put.

Is there was a slicker way of doing this?

Community
  • 1
  • 1
Nate Pet
  • 38,422
  • 114
  • 251
  • 393

9 Answers9

649

ES2017 Update

You can use the built-in String.prototype.padStart()

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

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

Not a lot of "slick" going on so far:

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

When you initialize an array with a number, it creates an array with the length set to that value so that the array appears to contain that many undefined elements. Though some Array instance methods skip array elements without values, .join() doesn't, or at least not completely; it treats them as if their value is the empty string. Thus you get a copy of the zero character (or whatever "z" is) between each of the array elements; that's why there's a + 1 in there.

Example usage:

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

pad(10, 4, '-'); // --10
Patrick McElhaney
  • 52,844
  • 37
  • 123
  • 157
Pointy
  • 371,531
  • 55
  • 528
  • 584
  • 2
    "When you initialize an array with a number, it creates an array with that many undefined elements. " - I don't think that's correct. It just sets the `length` property and join iterates `length` times. Access of an undefined property always returns `undefined`. See `"5" in Array(5)` vs `"0" in [1]` – Benjamin Gruenbaum Jul 24 '14 at 11:56
  • @BenjaminGruenbaum well that's one way of looking at it; in some sense the `length` property really is the essence of what an array is, so setting the `length` is all that's necessary. However, my understanding is that some modern runtime systems actually do allocate space, and I know they used to do so a long time ago. – Pointy Jul 24 '14 at 12:23
  • 4
    @Pointy allocating space is implementation detail that is invisible to the programmer (no implementations that are open and I'm aware of do that (Rhino, V8, SM, JSC) any implementation that allocates memory _and_ exposes the properties is in violation of the EcmaScript specification that is very clear about this (under "The Array constructor 15.4.2.2"). It's not a big deal and the answer is otherwise nice, it would be nice if you fixed this detail. – Benjamin Gruenbaum Jul 24 '14 at 12:27
  • @BenjaminGruenbaum yes, done. Thanks for the suggestion. – Pointy Jul 24 '14 at 12:34
  • 8
    thanks for your answer, but variables like "n" and "z" are not intuitive as to what they are doing. – DLeh May 21 '15 at 13:27
  • 2
    @DLeh "n" is the **n**umber to be padded, and "z" is (by default) **z**ero or else some other character to use for padding. – Pointy May 21 '15 at 13:29
  • 12
    do you really need an Array? `function pad(n, width, z) { while(n.length – Paolo Feb 18 '16 at 23:48
  • No, you don't *need* an array, but `Array.prototype.join()` is pretty heavily optimized. – Pointy Feb 19 '16 at 02:28
  • 1
    @Paolo Yours is arguably a better solution as it is faster. Depending on the browser it ranges from marginal to significant, but always quicker in my tests. +1 – ObjectType Apr 25 '16 at 21:22
  • 18
    "Slick", compact, and extensible. `function pad(n, width=3, z=0) {return (String(z).repeat(width) + String(n)).slice(String(n).length)}` – Gui Weinmann Jun 01 '16 at 20:55
  • 2
    Clever is good, but not at the expense of readability – Sarsaparilla Feb 10 '18 at 18:39
  • 2
    @HaiPhan I would be pretty nervous around a JavaScript programmer who didn't know what `.join()` does. – Pointy Feb 10 '18 at 21:37
  • string.repeat redux `const s = String(n); return String(z).repeat(Math.max(0, width - s.length)) + s` no slice() necessary – Jamie Pate Feb 26 '19 at 21:12
  • 1
    @JamiePate yes this answer is a little old :) Also I'm not sure that works everywhere, even now in 2019. – Pointy Feb 26 '19 at 21:35
  • Using Ecmascript2015, the following code is more compliant: `static pad(n, width, z) { z = z || '0'; n = n.toString(); return n.length >= width ? n : Array.from({length: width - n.length + 1}).join(z) + n; }` – Dominique Vienne Apr 03 '20 at 06:58
  • Not optimal as it takes many operations. – Code Guy Sep 21 '20 at 06:14
273
function padToFour(number) {
  if (number<=9999) { number = ("000"+number).slice(-4); }
  return number;
}

Something like that?

Bonus incomprehensible-but-slicker single-line ES6 version:

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

ES6isms:

  • let is a block scoped variable (as opposed to var’s functional scoping)
  • => is an arrow function that among other things replaces function and is prepended by its parameters
  • If a arrow function takes a single parameter you can omit the parentheses (hence number =>)
  • If an arrow function body has a single line that starts with return you can omit the braces and the return keyword and simply use the expression
  • To get the function body down to a single line I cheated and used a ternary expression
austin_ce
  • 813
  • 11
  • 27
Robin Whittleton
  • 5,612
  • 3
  • 35
  • 60
  • 1
    It’s simple but not that novel; I had to do something similar recently and found that approach online. – Robin Whittleton Apr 09 '12 at 15:48
  • 5
    Only took a vote off, because this isn't a modular approach (only works with 4 digits). Of course, it is a specific answer to a specific question, but including a length option would be better (like other answers). – doubleJ Nov 04 '13 at 19:26
  • 1
    I love the usage of slice. However as @doubleJ mentioned please note that a limitation of this approach is that will truncate the number to its last 4 digits. – Jorge Orpinel Mar 23 '14 at 00:50
  • 9
    Actually @JorgeOrpinel it will not truncate. The if statement causes the slice operation to only operate on numbers with four or fewer digits. A five-digit number has a value of at least 10000, which is not <= 9999. – Luke Griffiths Jun 26 '14 at 16:50
  • @RobinWhittleton If you found this approach online it is good practice include a link to the source to give the source the credits for the solution. Read also [here](http://meta.stackexchange.com/a/24618/262970). – Wilt May 19 '16 at 10:16
  • 1
    This was a while back, but as far as I remember I’d found it a good 6-12 months earlier and it had lodged in my head. If I had a link I’d definitely have added it. – Robin Whittleton May 19 '16 at 10:46
  • 1
    It's slick, but note that this function will **return different types** depending on the value of it's input: `Number` for numbers less than 1000 and `String` for greater numbers. This kind of frivolous treatment of types is a source of countless bugs in JS programs. I would suggest to also cast the value from the `else` branch to `String`: `... : "" + number`. – Tad Lispy Feb 20 '18 at 16:36
  • ES6 version would be readable if you added parentheses: let padToFour = number => (number <= 9999 ? ("000"+number).slice(-4) : number); – Basic Block May 08 '18 at 06:26
  • also, shouldn't it be `number < 999`? if number >= 1000, it's already 4 digits long, and the `('000'+number).slice(-4)` just returns number – BM- Sep 27 '18 at 06:48
  • 3
    I think we've made backwards progress since the days of `sprintf (padToFour, "%04d", number);` – gregn3 Aug 07 '19 at 01:45
  • I think this is a smart hack, but did we forget about for loops? Why would we use uselessly memory if we can do it in a nice way? – Ambrus Tóth May 27 '20 at 07:59
228

Try:

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

Now test:

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


In ECMAScript 2017 , we have new method padStart and padEnd which has below syntax.

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

So now we can use

const str = "5";
str.padStart(4, "0"); // "0005"
diEcho
  • 50,018
  • 37
  • 156
  • 230
69

Funny, I recently had to do this.

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

Use like:

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

Not beautiful, but effective.

Peter C
  • 5,821
  • 23
  • 37
  • @doubleJ Pointy's and mine are actually very similar, if not identical, except his has the feature of being able to pad with something other than 0. You could use his like `pad(15, 3)` much in the same way mine is used. – Peter C Nov 06 '13 at 22:02
  • I [wrote a similar answer](http://stackoverflow.com/a/21176213/908879), I first turn the num to str and use `return (Array(Math.max(5-str.length, 0)).join("0") + str);`, just droping this in case the other Q gets deleted – ajax333221 Jan 17 '14 at 19:57
  • 2
    To handle negative numbers, use the absolute value of the number then tack on a negative sign ('-') to the end result. `(number < 0 ? '-' : '') + Array(Math.max(digits - String(value).length + 1, 0)).join(0) + value` where 'value' is `Math.abs(number)`. – Neil Monroe Feb 20 '15 at 22:26
  • I like this solution a lot @NeilMonroe, but would you care to break it down for us? It's not very readable as a comment. :) – J.M. Janzen Jun 01 '20 at 21:36
26

You did say you had a number-

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
  • 94,076
  • 30
  • 99
  • 125
  • 2
    Love to know why this is not getting up-voted. Seems the most logical and complete solution. Example usage var v=2; v.padZero(4); v.padZero(4,'+'); produces '0002' '+++2' – rob Dec 15 '13 at 22:17
  • 1
    I've been looking to pad with leading zeros and this is my chosen solution. Should be more upvotes. – Mikebert4 Oct 16 '15 at 11:32
  • 2
    because this is too specific a solution... ``` String.prototype.lpad = function(len, c){ var s= '', c= c || ' ', len= (len || 2)-this.length; while(s.length – MrMesees Nov 07 '15 at 10:25
  • Also just realized four spaces for markdown is not working in these comment fields – MrMesees Nov 07 '15 at 10:28
14

You could do something like this:

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

Edit: This was just a basic idea for a function, but to add support for larger numbers (as well as invalid input), this would probably be better:

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

This does 2 things:

  1. If the number is larger than the specified size, it will simply return the number.
  2. Using Math.floor(num) in place of ~~num will support larger numbers.
Robert Messerle
  • 2,996
  • 12
  • 18
  • 2
    `pad(1111111111111, 10)` returns `714581447` – Serkan Yersen Mar 31 '14 at 21:38
  • 2
    This is due to the number being too large for the method used in my original solution (~~num). In order to support larger numbers, I added a new version of this function that uses Math.floor(). In addition to this, the number you provided was larger than the size you specified, so I added a check for this scenario. – Robert Messerle Apr 01 '14 at 23:10
  • This solution is not useful because 1) only works for small values of size, 2) cannot handle decimal places: e.g. pad(0.3333,10) = '0000000000' – Ron Wertlen Aug 13 '15 at 13:23
3

This is not really 'slick' but it's faster to do integer operations than to do string concatenations for each padding 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 );
    }
}

This function is also hardcoded to your particular need (4 digit padding), so it's not generic.

xxbbcc
  • 15,756
  • 5
  • 42
  • 76
3

For fun, instead of using a loop to create the extra zeros:

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
  • 271,922
  • 98
  • 616
  • 693
  • How about `new Array(needed + 1).join('0')` instead of that expensive exponentiation? :-) – Pointy Apr 09 '12 at 13:20
  • 2
    Note that this will only work for lengths below a certain size, before the numbers switch over to scientific notation. Pointy's Array usage is more effective in general. (@Pointy: because this is just for fun :) – Phrogz Apr 09 '12 at 13:21
  • 1
    Yes I know. That's like the only legit use of the Array constructor so it deserves an airing :-) – Pointy Apr 09 '12 at 13:23
2

Since you mentioned it's always going to have a length of 4, I won't be doing any error checking to make this slick. ;)

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

Idea: Simply replace '0000' with number provided... Issue with that is, if input is 0, I need to hard-code it to return '0000'. LOL.

This should be slick enough.

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

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
DashK
  • 2,504
  • 1
  • 19
  • 27
  • Here is some random output that proves this is not as slick as you thought it was... 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 May 25 '18 at 07:13
  • not perfect, but I like the idea. Somebody's thinking outside the box :) ... Perhaps replace the `4-Math.ceil(...)` part with ``4-`${input}`.length()`` – bvdb Jan 20 '19 at 23:09