Milliseconds in Lap Time Average dropping the Zero in Tenths place - javascript

I am using code I found on this site to average lap times in MM:SS.mmm (Averaging Times using Javascript)
It works great until the result has a zero in the tenths place. For example, the result should be 01:00.096 however, the zero is dropped and the answer is 01:00.96
I have simplified the input of 'times' to highlight the problem.
I have looked at different formatting issues, tried converting the strings to numbers and I've looked at the offsetify function thinking it was somehow interpreting the milliseconds incorrectly.
I am a novice at JavaScript with no formal training but enjoy hobby-programming. I have learned a lot from the examples on this site for use in my own little apps.
var times = ['01:00.096'];
var date = 0
var result = '';
function offsetify(t)
{
return t < 10 ? '0' + t : t;
}
for(var x = 0; x < times.length; x++ ) {
var tarr = times[x].split(':');
date += new Date(0, 0, 0, 0, tarr[0], tarr[1].split('.')[0], tarr[1].split('.')[1]).getTime();
}
var avg = new Date(date/times.length);
result = offsetify(avg.getMinutes()) + ':' + offsetify(avg.getSeconds()) + '.' + offsetify(avg.getMilliseconds());

The reason you see the 0 dropping is because in the offsetify function you have
return t < 10 ? '0' + t : t;
and you are passing it the value 96, which is not less than 10, so the function returns 96.
If you are able to find a datetime-formatting library like date-fns or moment, and you should use one, then great! Let the library do the work for you.
If you would like the practice, which is great for learning, use
s.padStart(3, '0')
for milliseconds, and
s.padStart(2, '0')
for minutes. For example, for your milliseconds:
> "5".padStart(3, "0")
'005'
> "55".padStart(3, "0")
'055'
> "383".padStart(3, "0")
'383'

Your function offsetify(t) appends a 0 in case your minutes/seconds is only single-digit - however milliseconds should be 3 digits!
You could create a new function that appends 0 if it is already 2 digits (less than 100), and 00 if it is only single-digit (less than 10) and just returns the result if it is already 3 digits.
function offsetifyMilliseconds(t)
{
return t < 10 ? '00' + t : t < 100 ? '0' + t : t;
}
and then do
result = offsetify(avg.getMinutes()) + ':' + offsetify(avg.getSeconds()) + '.' + offsetifyMilliseconds(avg.getMilliseconds());
However recent versions of Javascript (from ES2017) has access to the .padStart() function on any string:
The padStart() method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start (left) of the current string.
-- String.prototype.padStart() - MDN
Using this would make your code much more readable (although you'd have to convert the numeric result to a string first). You could even change your offsetify function to use this method, and prevent code duplication!
In the example below I have defined 2 as the default padding length for the method, but you can pass an additional parameter to the function when you want to use it for milliseconds:
var times = ['01:00.096'];
var date = 0
var result = '';
function offsetify(t, len = 2)
{
return t.toString().padStart(len, '0');
}
for(var x = 0; x < times.length; x++ ) {
var tarr = times[x].split(':');
date += new Date(0, 0, 0, 0, tarr[0], tarr[1].split('.')[0], tarr[1].split('.')[1]).getTime();
}
var avg = new Date(date/times.length);
var minutes = offsetify(avg.getMinutes());
var seconds = offsetify(avg.getSeconds());
var milliseconds = offsetify(avg.getMilliseconds(), 3);
result = minutes + ':' + seconds + ':' + milliseconds;
console.log(result);

Related

JS regex match returning null

I'm trying to do a coding challenge on Coderbyte. I have to find the difference in minutes between two inputted times (eg: "12:00am-12:00pm"). This is my code:
function getMinutes(str) {
var pattern = /(\d+)\:(\d+)([ap]m)/i;
var matches = str.toString().match(pattern);
**// return matches**
if (matches == null) {
return matches;
}
var hour = parseInt(matches[1]);
var minutes = parseInt(matches[2]);
var extra = (matches[3] == "am") ? 0 : 720;
if (hour == 12)
hour = 0;
return (hour * 60) + minutes + extra;
}
function CountingMinutesI(str) {
var chunks = str.split("-");
var minuteA = getMinutes(chunks[0]), minuteB = getMinutes(chunks[1]);
return getMinutes(minuteA) + " " + getMinutes(minuteB);
}
// keep this function call here
// to see how to enter arguments in JavaScript scroll down
CountingMinutesI(readline());
For some reason in getMinutes, matches is null even though it shouldn't be. If you uncomment the bolded line that says "return matches", then it will give me the valid array with all the matches. But if I comment that line out, then matches becomes null. Why? This is so strange.
There is simple oversight in CountingMinutesI(). You are going getMinutes twice. Replace
return getMinutes(minuteA) + " " + getMinutes(minuteB);
With
return minuteA + " " + minuteB;
In the CountingMinutesI function, you are calling getMinutes() a total of 4 times, one for the first chunk, one for the second chunk, one with the result of the first call (0), and one with the result of the second call (720).
Those second two calls are the problem, they result in the function trying to match the regex against "0" and "720" respectively, neither of which will work.

Calculate in Javascript not working

I want to calculate in Javascript but having Strange Problems.
It just adds an 1 to my String but it should calculate it. I am converting my Strings to Int with the parseInt() Function and a am calculating like this: sec = sec + 1;
var calc= parseInt($(this).find("input[name=calc]").val());
calc = calc + 1;
Your string must not be empty if don't want NaN. First check if you get an empty string:
var cal = null;
if ( $(this).find("input[name=calc]").val() ) {
cal = parseInt( $(this).find("input[name=calc]").val(), 10 );
cal++;
}
if(!!sec){
sec = parseInt(sec, 10) + 1;
alert(sec);
}
Or, in your scenario:
var fieldvalue = $(this).find("input[name=calc]").val(), calc;
if(!!fieldvalue){
calc = parseInt(fieldvalue, 10);
calc += 1;
alert(calc);
}
Do you have more code to express. It may just be coming out to 1, because sec is not set as a number
In javascript, the + operator is used for addition and concatenation of strings.
As javascript is weakly typed, you have to add information about the type. Here are two solutions:
Substract 0 from the string
sec = (sec-0) + 1;
Add unary + operator to the string
sec = (+sec) + 1;

How can I find the length of a number?

I'm looking to get the length of a number in JavaScript or jQuery?
I've tried value.length without any success, do I need to convert this to a string first?
var x = 1234567;
x.toString().length;
This process will also work forFloat Number and for Exponential number also.
Ok, so many answers, but this is a pure math one, just for the fun or for remembering that Math is Important:
var len = Math.ceil(Math.log(num + 1) / Math.LN10);
This actually gives the "length" of the number even if it's in exponential form. num is supposed to be a non negative integer here: if it's negative, take its absolute value and adjust the sign afterwards.
Update for ES2015
Now that Math.log10 is a thing, you can simply write
const len = Math.ceil(Math.log10(num + 1));
Could also use a template string:
const num = 123456
`${num}`.length // 6
You have to make the number to string in order to take length
var num = 123;
alert((num + "").length);
or
alert(num.toString().length);
I've been using this functionality in node.js, this is my fastest implementation so far:
var nLength = function(n) {
return (Math.log(Math.abs(n)+1) * 0.43429448190325176 | 0) + 1; 
}
It should handle positive and negative integers (also in exponential form) and should return the length of integer part in floats.
The following reference should provide some insight into the method:
Weisstein, Eric W. "Number Length." From MathWorld--A Wolfram Web Resource.
I believe that some bitwise operation can replace the Math.abs, but jsperf shows that Math.abs works just fine in the majority of js engines.
Update: As noted in the comments, this solution has some issues :(
Update2 (workaround) : I believe that at some point precision issues kick in and the Math.log(...)*0.434... just behaves unexpectedly. However, if Internet Explorer or Mobile devices are not your cup of tea, you can replace this operation with the Math.log10 function. In Node.js I wrote a quick basic test with the function nLength = (n) => 1 + Math.log10(Math.abs(n) + 1) | 0; and with Math.log10 it worked as expected. Please note that Math.log10 is not universally supported.
There are three way to do it.
var num = 123;
alert(num.toString().length);
better performance one (best performance in ie11)
var num = 123;
alert((num + '').length);
Math (best performance in Chrome, firefox but slowest in ie11)
var num = 123
alert(Math.floor( Math.log(num) / Math.LN10 ) + 1)
there is a jspref here
http://jsperf.com/fastest-way-to-get-the-first-in-a-number/2
You should go for the simplest one (stringLength), readability always beats speed. But if you care about speed here are some below.
Three different methods all with varying speed.
// 34ms
let weissteinLength = function(n) {
return (Math.log(Math.abs(n)+1) * 0.43429448190325176 | 0) + 1;
}
// 350ms
let stringLength = function(n) {
return n.toString().length;
}
// 58ms
let mathLength = function(n) {
return Math.ceil(Math.log(n + 1) / Math.LN10);
}
// Simple tests below if you care about performance.
let iterations = 1000000;
let maxSize = 10000;
// ------ Weisstein length.
console.log("Starting weissteinLength length.");
let startTime = Date.now();
for (let index = 0; index < iterations; index++) {
weissteinLength(Math.random() * maxSize);
}
console.log("Ended weissteinLength length. Took : " + (Date.now() - startTime ) + "ms");
// ------- String length slowest.
console.log("Starting string length.");
startTime = Date.now();
for (let index = 0; index < iterations; index++) {
stringLength(Math.random() * maxSize);
}
console.log("Ended string length. Took : " + (Date.now() - startTime ) + "ms");
// ------- Math length.
console.log("Starting math length.");
startTime = Date.now();
for (let index = 0; index < iterations; index++) {
mathLength(Math.random() * maxSize);
}
First convert it to a string:
var mynumber = 123;
alert((""+mynumber).length);
Adding an empty string to it will implicitly cause mynumber to turn into a string.
Well without converting the integer to a string you could make a funky loop:
var number = 20000;
var length = 0;
for(i = number; i > 1; ++i){
++length;
i = Math.floor(i/10);
}
alert(length);​
Demo: http://jsfiddle.net/maniator/G8tQE/
I got asked a similar question in a test.
Find a number's length without converting to string
const numbers = [1, 10, 100, 12, 123, -1, -10, -100, -12, -123, 0, -0]
const numberLength = number => {
let length = 0
let n = Math.abs(number)
do {
n /= 10
length++
} while (n >= 1)
return length
}
console.log(numbers.map(numberLength)) // [ 1, 2, 3, 2, 3, 1, 2, 3, 2, 3, 1, 1 ]
Negative numbers were added to complicate it a little more, hence the Math.abs().
I'm perplex about converting into a string the given number because such an algorithm won't be robust and will be prone to errors: it will show all its limitations especially in case it has to evaluate very long numbers. In fact before converting the long number into a string it will "collapse" into its exponential notation equivalent (example: 1.2345e4). This notation will be converted into a string and this resulting string will be evaluated for returning its length. All of this will give a wrong result. So I suggest not to use that approach.
Have a look at the following code and run the code snippet to compare the different behaviors:
let num = 116234567891011121415113441236542134465236441625344625344625623456723423523429798771121411511034412365421344652364416253446253446254461253446221314623879235441623683749283441136232514654296853446323214617456789101112141511344122354416236837492834411362325146542968534463232146172368374928344113623251465429685;
let lenFromMath;
let lenFromString;
// The suggested way:
lenFromMath = Math.ceil(Math.log10(num + 1)); // this works in fact returns 309
// The discouraged way:
lenFromString = String(num).split("").length; // this doesn't work in fact returns 23
/*It is also possible to modify the prototype of the primitive "Number" (but some programmer might suggest this is not a good practice). But this is will also work:*/
Number.prototype.lenght = () => {return Math.ceil(Math.log10(num + 1));}
lenFromPrototype = num.lenght();
console.log({lenFromMath, lenFromPrototype, lenFromString});
A way for integers or for length of the integer part without banal converting to string:
var num = 9999999999; // your number
if (num < 0) num = -num; // this string for negative numbers
var length = 1;
while (num >= 10) {
num /= 10;
length++;
}
alert(length);
I would like to correct the #Neal answer which was pretty good for integers, but the number 1 would return a length of 0 in the previous case.
function Longueur(numberlen)
{
var length = 0, i; //define `i` with `var` as not to clutter the global scope
numberlen = parseInt(numberlen);
for(i = numberlen; i >= 1; i)
{
++length;
i = Math.floor(i/10);
}
return length;
}
To get the number of relevant digits (if the leading decimal part is 0 then the whole part has a length of 0) of any number separated by whole part and decimal part I use:
function getNumberLength(x) {
let numberText = x.toString();
let exp = 0;
if (numberText.includes('e')) {
const [coefficient, base] = numberText.split('e');
exp = parseInt(base, 10);
numberText = coefficient;
}
const [whole, decimal] = numberText.split('.');
const wholeLength = whole === '0' ? 0 : whole.length;
const decimalLength = decimal ? decimal.length : 0;
return {
whole: wholeLength > -exp ? wholeLength + exp : 0,
decimal: decimalLength > exp ? decimalLength - exp : 0,
};
}
var x = 1234567;
String(x).length;
It is shorter than with .toString() (which in the accepted answer).
Try this:
$("#element").text().length;
Example of it in use
Yes you need to convert to string in order to find the length.For example
var x=100;// type of x is number
var x=100+"";// now the type of x is string
document.write(x.length);//which would output 3.

get the number of n digit in a 2+ digit number

For example, getting "5" in "256". The closest I've gotten is Math.floor(256/10)), but that'll still return the numbers in front. Is there any simple way to get what I want or would I have to make a big function for it? Also, for clarity: "n digit" would be defined. Example, getDigit(2,256) would return 5 (second digit)
Math.floor((256 / 10) % 10)
or more generally:
Math.floor(N / (Math.pow(10, n)) % 10)
where N is the number to be extracted, and n is the position of the digit. Note that this counts from 0 starting from the right (i.e., the least significant digit = 0), and doesn't account for invalid values of n.
how about
(12345 + "")[3]
or
(12345 + "").charAt(3)
to count from the other end
[length of string - digit you want] so if you want the 2 it's:
5 - 4 = 1
(12345 + "")[1] = "2"
function getNumber (var num, var pos){
var sNum = num + "";
if(pos > sNum.length || pos <= 0){return "";}
return sNum[sNum.length - pos];
}
First, you need to cast the number to a string, then you can access the character as normal:
var num = 256;
var char = num.toString()[1]; // get the 2nd (0-based index) character from the stringified version of num
Edit: Note also that, if you want to access it without setting the number as a variable first, you need a double dot .. to access the function:
var char = 256..toString()[1];
The first dot tells the interpreter "this is a number"; the second accesses the function.
Convert to string and substring(2,2)?
This should do it:
function getDigit ( position, number ) {
number = number + ""; // convert number to string
return number.substr ( position + 1, 1 ); // I'm adding 1 to position, since 0 is the position of the first character and so on
}
Try this, last line is key:
var number = 12345;
var n = 2;
var nDigit = parseInt((number + '').substr(1,1));
If you want to try to do everything mathematically:
var number = 256;
var digitNum = 2;
var digit = ((int)(number/(Math.pow(10,digitNum-1))%10;
This code counts the digit from the right starting with 1, not 0. If you wish to change it to start at 0, delete the -1 portion in the call.
If you wish to count from the left, it gets more complicated and similar to other solutions:
var number = 256;
var digitNum = 2;
var digit = ((int)(number/(Math.pow(10,number.tostring().length-digitNum))%10;
edit:
Also, this assumes you want base 10 for your number system, but both of those will work with other bases. All you need to do is change instances of 10 in the final line of code to the number representing the base for the number system you'd like to use. (ie. hexadecimal =16, binary = 2)
// You do not say if you allow decimal fractions or negative numbers-
// the strings of those need adjusting.
Number.prototype.nthDigit= function(n){
var s= String(this).replace(/\D+/g,'');
if(s.length<=n) return null;
return Number(s.charAt(n))
}
use variable "count" to control loop
var count = 1; //starting 1
for(i=0; i<100; i++){
console.log(count);
if(i%10 == 0) count++;
}
output will fill
1
2
3
4
5
6
7
8
9

How can I pad a value with leading zeros?

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").
I can't believe all the complex answers on here... Just use this:
var zerofilled = ('0000'+n).slice(-4);
let n = 1
var zerofilled = ('0000'+n).slice(-4);
console.log(zerofilled)
Simple way. You could add string multiplication for the pad and turn it into a function.
var pad = "000000";
var n = '5';
var result = (pad+n).slice(-pad.length);
As a function,
function paddy(num, padlen, padchar) {
var pad_char = typeof padchar !== 'undefined' ? padchar : '0';
var pad = new Array(1 + padlen).join(pad_char);
return (pad + num).slice(-pad.length);
}
var fu = paddy(14, 5); // 00014
var bar = paddy(2, 4, '#'); // ###2
Since ECMAScript 2017 we have padStart:
const padded = (.1 + "").padStart(6, "0");
console.log(`-${padded}`);
Before ECMAScript 2017
With toLocaleString:
var n=-0.1;
var res = n.toLocaleString('en', {minimumIntegerDigits:4,minimumFractionDigits:2,useGrouping:false});
console.log(res);
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!
XDR came up with a logarithmic variation that seems to perform better.
WARNING: This function fails if num equals zero (e.g. zeropad(0, 2))
function zeroPad (num, numZeros) {
var an = Math.abs (num);
var digitCount = 1 + Math.floor (Math.log (an) / Math.LN10);
if (digitCount >= numZeros) {
return num;
}
var zeroString = Math.pow (10, numZeros - digitCount).toString ().substr (1);
return num < 0 ? '-' + zeroString + an : zeroString + an;
}
Speaking of performance, tomsmeding compared the top 3 answers (4 with the log variation). Guess which one majorly outperformed the other two? :)
Modern browsers now support padStart, you can simply now do:
string.padStart(maxLength, "0");
Example:
string = "14";
maxLength = 5; // maxLength is the max string length, not max # of fills
res = string.padStart(maxLength, "0");
console.log(res); // prints "00014"
number = 14;
maxLength = 5; // maxLength is the max string length, not max # of fills
res = number.toString().padStart(maxLength, "0");
console.log(res); // prints "00014"
Here's what I used to pad a number up to 7 characters.
("0000000" + number).slice(-7)
This approach will probably suffice for most people.
Edit: If you want to make it more generic you can do this:
("0".repeat(padding) + number).slice(-padding)
Edit 2: Note that since ES2017 you can use String.prototype.padStart:
number.toString().padStart(padding, "0")
Unfortunately, there are a lot of needless complicated suggestions for this problem, typically involving writing your own function to do math or string manipulation or calling a third-party utility. However, there is a standard way of doing this in the base JavaScript library with just one line of code. It might be worth wrapping this one line of code in a function to avoid having to specify parameters that you never want to change like the local name or style.
var amount = 5;
var text = amount.toLocaleString('en-US',
{
style: 'decimal',
minimumIntegerDigits: 3,
useGrouping: false
});
This will produce the value of "005" for text. You can also use the toLocaleString function of Number to pad zeros to the right side of the decimal point.
var amount = 5;
var text = amount.toLocaleString('en-US',
{
style: 'decimal',
minimumFractionDigits: 2,
useGrouping: false
});
This will produce the value of "5.00" for text. Change useGrouping to true to use comma separators for thousands.
Note that using toLocaleString() with locales and options arguments is standardized separately in ECMA-402, not in ECMAScript. As of today, some browsers only implement basic support, i.e. toLocaleString() may ignore any arguments.
Complete Example
If the fill number is known in advance not to exceed a certain value, there's another way to do this with no loops:
var fillZeroes = "00000000000000000000"; // max number of zero fill ever asked for in global
function zeroFill(number, width) {
// make sure it's a string
var input = number + "";
var prefix = "";
if (input.charAt(0) === '-') {
prefix = "-";
input = input.slice(1);
--width;
}
var fillAmt = Math.max(width - input.length, 0);
return prefix + fillZeroes.slice(0, fillAmt) + input;
}
Test cases here: http://jsfiddle.net/jfriend00/N87mZ/
The quick and dirty way:
y = (new Array(count + 1 - x.toString().length)).join('0') + x;
For x = 5 and count = 6 you'll have y = "000005"
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;
}
ECMAScript 2017:
use padStart or padEnd
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
More info:
https://github.com/tc39/proposal-string-pad-start-end
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
I often use this construct for doing ad-hoc padding of some value n, known to be a positive, decimal:
(offset + n + '').substr(1);
Where offset is 10^^digits.
E.g., padding to 5 digits, where n = 123:
(1e5 + 123 + '').substr(1); // => 00123
The hexadecimal version of this is slightly more verbose:
(0x100000 + 0x123).toString(16).substr(1); // => 00123
Note 1: I like #profitehlolz's solution as well, which is the string version of this, using slice()'s nifty negative-index feature.
I really don't know why, but no one did it in the most obvious way. Here it's my implementation.
Function:
/** Pad a number with 0 on the left */
function zeroPad(number, digits) {
var num = number+"";
while(num.length < digits){
num='0'+num;
}
return num;
}
Prototype:
Number.prototype.zeroPad=function(digits){
var num=this+"";
while(num.length < digits){
num='0'+num;
}
return(num);
};
Very straightforward, I can't see any way how this can be any simpler. For some reason I've seem many times here on SO, people just try to avoid 'for' and 'while' loops at any cost. Using regex will probably cost way more cycles for such a trivial 8 digit padding.
In all modern browsers you can use
numberStr.padStart(numberLength, "0");
function zeroFill(num, numLength) {
var numberStr = num.toString();
return numberStr.padStart(numLength, "0");
}
var numbers = [0, 1, 12, 123, 1234, 12345];
numbers.forEach(
function(num) {
var numString = num.toString();
var paddedNum = zeroFill(numString, 5);
console.log(paddedNum);
}
);
Here is the MDN reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
I use this snippet to get a five-digits representation:
(value+100000).toString().slice(-5) // "00123" with value=123
The power of Math!
x = integer to pad
y = number of zeroes to pad
function zeroPad(x, y)
{
y = Math.max(y-1,0);
var n = (x / Math.pow(10,y)).toFixed(y);
return n.replace('.','');
}
This is the ES6 solution.
function pad(num, len) {
return '0'.repeat(len - num.toString().length) + num;
}
alert(pad(1234,6));
Not that this question needs more answers, but I thought I would add the simple lodash version of this.
_.padLeft(number, 6, '0')
I didn't see anyone point out the fact that when you use String.prototype.substr() with a negative number it counts from the right.
A one liner solution to the OP's question, a 6-digit zerofilled representation of the number 5, is:
console.log(("00000000" + 5).substr(-6));
Generalizing we'll get:
function pad(num, len) { return ("00000000" + num).substr(-len) };
console.log(pad(5, 6));
console.log(pad(45, 6));
console.log(pad(345, 6));
console.log(pad(2345, 6));
console.log(pad(12345, 6));
Don't reinvent the wheel; use underscore string:
jsFiddle
var numToPad = '5';
alert(_.str.pad(numToPad, 6, '0')); // Yields: '000005'
After a, long, long time of testing 15 different functions/methods found in this questions answers, I now know which is the best (the most versatile and quickest).
I took 15 functions/methods from the answers to this question and made a script to measure the time taken to execute 100 pads. Each pad would pad the number 9 with 2000 zeros. This may seem excessive, and it is, but it gives you a good idea about the scaling of the functions.
The code I used can be found here:
https://gist.github.com/NextToNothing/6325915
Feel free to modify and test the code yourself.
In order to get the most versatile method, you have to use a loop. This is because with very large numbers others are likely to fail, whereas, this will succeed.
So, which loop to use? Well, that would be a while loop. A for loop is still fast, but a while loop is just slightly quicker(a couple of ms) - and cleaner.
Answers like those by Wilco, Aleksandar Toplek or Vitim.us will do the job perfectly.
Personally, I tried a different approach. I tried to use a recursive function to pad the string/number. It worked out better than methods joining an array but, still, didn't work as quick as a for loop.
My function is:
function pad(str, max, padder) {
padder = typeof padder === "undefined" ? "0" : padder;
return str.toString().length < max ? pad(padder.toString() + str, max, padder) : str;
}
You can use my function with, or without, setting the padding variable. So like this:
pad(1, 3); // Returns '001'
// - Or -
pad(1, 3, "x"); // Returns 'xx1'
Personally, after my tests, I would use a method with a while loop, like Aleksandar Toplek or Vitim.us. However, I would modify it slightly so that you are able to set the padding string.
So, I would use this code:
function padLeft(str, len, pad) {
pad = typeof pad === "undefined" ? "0" : pad + "";
str = str + "";
while(str.length < len) {
str = pad + str;
}
return str;
}
// Usage
padLeft(1, 3); // Returns '001'
// - Or -
padLeft(1, 3, "x"); // Returns 'xx1'
You could also use it as a prototype function, by using this code:
Number.prototype.padLeft = function(len, pad) {
pad = typeof pad === "undefined" ? "0" : pad + "";
var str = this + "";
while(str.length < len) {
str = pad + str;
}
return str;
}
// Usage
var num = 1;
num.padLeft(3); // Returns '001'
// - Or -
num.padLeft(3, "x"); // Returns 'xx1'
First parameter is any real number, second parameter is a positive integer specifying the minimum number of digits to the left of the decimal point and third parameter is an optional positive integer specifying the number if digits to the right of the decimal point.
function zPad(n, l, r){
return(a=String(n).match(/(^-?)(\d*)\.?(\d*)/))?a[1]+(Array(l).join(0)+a[2]).slice(-Math.max(l,a[2].length))+('undefined'!==typeof r?(0<r?'.':'')+(a[3]+Array(r+1).join(0)).slice(0,r):a[3]?'.'+a[3]:''):0
}
so
zPad(6, 2) === '06'
zPad(-6, 2) === '-06'
zPad(600.2, 2) === '600.2'
zPad(-600, 2) === '-600'
zPad(6.2, 3) === '006.2'
zPad(-6.2, 3) === '-006.2'
zPad(6.2, 3, 0) === '006'
zPad(6, 2, 3) === '06.000'
zPad(600.2, 2, 3) === '600.200'
zPad(-600.1499, 2, 3) === '-600.149'
The latest way to do this is much simpler:
var number = 2
number.toLocaleString(undefined, {minimumIntegerDigits:2})
output: "02"
Just another solution, but I think it's more legible.
function zeroFill(text, size)
{
while (text.length < size){
text = "0" + text;
}
return text;
}
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;
};
My solution
Number.prototype.PadLeft = function (length, digit) {
var str = '' + this;
while (str.length < length) {
str = (digit || '0') + str;
}
return str;
};
Usage
var a = 567.25;
a.PadLeft(10); // 0000567.25
var b = 567.25;
b.PadLeft(20, '2'); // 22222222222222567.25
With ES6+ JavaScript:
You can "zerofill a number" with something like the following function:
/**
* #param number The number
* #param minLength Minimal length for your string with leading zeroes
* #return Your formatted string
*/
function zerofill(nb, minLength) {
// Convert your number to string.
let nb2Str = nb.toString()
// Guess the number of zeroes you will have to write.
let nbZeroes = Math.max(0, minLength - nb2Str.length)
// Compute your result.
return `${ '0'.repeat(nbZeroes) }${ nb2Str }`
}
console.log(zerofill(5, 6)) // Displays "000005"
With ES2017+:
/**
* #param number The number
* #param minLength Minimal length for your string with leading zeroes
* #return Your formatted string
*/
const zerofill = (nb, minLength) => nb.toString().padStart(minLength, '0')
console.log(zerofill(5, 6)) // Displays "000005"
Use recursion:
function padZero(s, n) {
s = s.toString(); // In case someone passes a number
return s.length >= n ? s : padZero('0' + s, n);
}
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"
function pad(toPad, padChar, length){
return (String(toPad).length < length)
? new Array(length - String(toPad).length + 1).join(padChar) + String(toPad)
: toPad;
}
pad(5, 0, 6) = 000005
pad('10', 0, 2) = 10 // don't pad if not necessary
pad('S', 'O', 2) = SO
...etc.
Cheers

Categories

Resources