views:

1130

answers:

9

What is the recommended way to zerofill a value in JavaScript? I imagine I could build a custom function to pad zeros on to a typecasted value, but I'm wondering if there is a more direct way to do this?

Note: By "zerofilled" I mean it in the database sense of the word (where a 6-digit zerofilled representation of the number 5 would be "000005").

+6  A: 

A simple function is all you need

function zeroFill( number, width )
{
  width -= number.toString().length;
  if ( width > 0 )
  {
    return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
  }
  return number;
}

you could bake this into a library if you want to conserve namespace or whatever. Like with jQuery's extend.

Peter Bailey
+1 that is a clever use of join
Gabe Moothart
Nice approach! I like it!. Watch out for numbers that are longer than your width though...
coderjoe
I added "robustness" to the guard condition
Peter Bailey
Now you just need to take care of numbers like 50.1234 and you've got a readable version of my solution below! I did, however, assume that we were just left padding, not overall padding.
coderjoe
updated to work with decimals. It's a bit uglier now though =/
Peter Bailey
+2  A: 

Here's a quick function I came up with to do the job. If anyone has a simpler approach, feel free to share!

function zerofill(number, length) {
    // Setup
    var result = number.toString();
    var pad = length - result.length;

    while(pad > 0) {
     result = '0' + result;
     pad--;
    }

    return result;
}
Wilco
I don't think there will be a "simpler" solution - it will always be a function of some sort. We could have a algorithm discussion, but at the end of the day, you'll still end up with a function that zerofills a number.
Peter Bailey
My general advice is to use "for" loops as they are generally more stable and faster in ECMAScript languages (ActionScript 1-3, and JavaScript)
Christopher W. Allen-Poole
Or, skip iteration altogether ;)
Peter Bailey
Simpler function? Probably not. One that doesn't loop? That is possible... though the algorithm isn't entirely trivial.
coderjoe
+3  A: 

I actually had to come up with something like this recently. I figured there had to be a way to do it without using loops.

This is what I came up with.

function zeroPad(num, numZeros) {
 var n = Math.abs(num);
 var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
 var zeroString = Math.pow(10,zeros).toString().substr(1);
 if( num < 0 ) {
  zeroString = '-' + zeroString;
 }

 return zeroString+n;
}

Then just use it providing a number to zero pad:

> zeroPad(50,4);
"0050"

If the number is larger than the padding, the number will expand beyond the padding:

> zeroPad(51234, 3);
"51234"

Decimals are fine too!

> zeroPad(51.1234, 4);
"0051.1234"

If you don't mind polluting the global namespace you can add it to Number directly:

Number.prototype.leftZeroPad = function(numZeros) {
 var n = Math.abs(this);
 var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
 var zeroString = Math.pow(10,zeros).toString().substr(1);
 if( this < 0 ) {
  zeroString = '-' + zeroString;
 }

 return zeroString+n;
}

And if you'd rather have decimals take up space in the padding:

Number.prototype.leftZeroPad = function(numZeros) {
 var n = Math.abs(this);
 var zeros = Math.max(0, numZeros - n.toString().length );
 var zeroString = Math.pow(10,zeros).toString().substr(1);
 if( this < 0 ) {
  zeroString = '-' + zeroString;
 }

 return zeroString+n;
}

Cheers!

coderjoe
Updated to take care of negative numbers.
coderjoe
Updated again to show how it might be used to include decimal places in the amount of padding used.
coderjoe
+1 quirky, but clever
Gabe Moothart
+1  A: 

This method isn't faster, but it's fairly native.

zeroPad = function (num, count) {
    return [Math.pow(10, count - num.toString().length), num].join('').substr(1);
};
+1  A: 
function zeroPad(num,digits){ return ((num/Math.pow(10,digits))+'').slice(2) }
Paul Irish
+1 welcome to SO
redsquare
this has a couple of issues: it trims off zeroes from the right `zeroPad(50, 5) == "0005"`, and trims off numbers from the left if it's longer than the padding width: `zeroPad(123456, 5) == "23456"`
nickf
heh. good call.
Paul Irish
+1  A: 

This one is less native, but may be the fastest...

zeroPad = function (num, count) {
    var pad = (num + '').length - count;
    while(--pad > -1) {
        num = '0' + num;
    }
    return num;
};
i think you want to do `pad = count - (num + '').length`. negative numbers aren't handled well, but apart from that, it's not bad. +1
nickf
A: 

Our tests were bogus because mine had a typo.

zeroPad = function (num, count) {
    return ((num / Math.pow(10, count)) + '').substr(2);
};

Paul's is the fastest, but I think .substr is faster than .slice even if it is one character more ;)

A: 

Some monkeypatching also works

String.prototype.padLeft = function (n, c) {
  if (isNaN(n))
    return null;
  c = c || "0";
  return (new Array(n).join(c).substring(0, this.length-n)) + this; 
};
var paddedValue = "123".padLeft(6); // returns "000123"
var otherPadded = "TEXT".padLeft(8, " "); // returns "    TEXT"
Rodrigo
-1 monkeypatching the toplevel namespacing in javascript is bad practice.
Jeremy Wall
True for Object and Array objects, but String is not bad
Rodrigo
A: 

Hi, just wanted to make the comment (but i don't have enough points) that the highest voted answer fails with negative numbers and decimals

function padNumber(n,pad) {
    p = Math.pow(10,pad);
    a = Math.abs(n);
    g = (n<0);
    return (a < p) ?  ((g ? '-' : '') + (p+a).toString().substring(1)) : n;
}

padNumber( -31.235, 5);

"-00031.235"