How to keep leading zero in a timetable - javascript

I've got a selection of times, but I want to keep the leading zero:
var fastTrainReading = [0943, 0957, 1006, 1013 , 1027, 1036, 1043, 1057, 1106, 1113, 1127, 1136, 1213, 1227, 1236, 1243, 1257, 1306, 1313, 1327, 1336, 1343, 1357, 1406, 1413, 1427, 1436, 1443, 1457, 1506, 1513, 1527, 1537, 1543, 1559, 1606, 1613, 1627, 1636, 1643, 1657, 1704, 1718, 1728, 1735, 1749, 1758, 1816, 1830, 1847, 1859, 1906, 1911, 1930, 1936, 1941, 1959, 2006, 2017, 2027];
This is the math performed:
var currentTime = hour*100 + mins;
if ((day == 0) || (day == 6)) {
document.write ("There are no buses today");
} else {
var displayCount = 0;
var TrainStr1 = "";
for (var i=0, len=fastTrainReading.length; i<len; ++i) {
if ((fastTrainReading[i] > currentTime) && (displayCount < 2)) {
displayCount = displayCount+1;
TrainStr1=TrainStr1 + fastTrainReading[i] + "<br/>";
}
}
}
document.write (TrainStr1)
I had a pretty good search through, if I missed something feel free to abuse me (but point me in the right direction).

Simplest solution is to store your time data as strings e.g. var fastTrainReading = ['0943', .... JavaScript will cast to integer for you in your calculation routines.
For a comprehensive string formatting solution that adheres to conventional principles, try sprintf() for javascript: http://www.diveintojavascript.com/projects/javascript-sprintf

You can try to use .toString() like: TrainStr1=TrainStr1 +fastTrainReading[i].toString()+ "<br/>"; alt to save your times as strings.

By default you won't get the leading zeroes.
As you know the length of TrainStr1 is 4, you can use the following function to get zeroes.
function formatted(time) {
var s = "0000" + time;
return s.substr(s.length-4); }
You can call the function 'formatted' before using document.write

You need to zero pad your numbers.
Number.prototype.zf = function _zeroFormat(digits)
{
var n = this.toString(), pLen = digits - n.length;
for ( var i = 0; i < pLen; i++)
{
n = '0' + n;
}
return n;
}
if ((fastTrainReading[i] > currentTime.zf(4)) && (displayCount < 2)) {
displayCount = displayCount+1;
TrainStr1=TrainStr1 + fastTrainReading[i] + "<br/>";
}
Once you've normalized all of your numbers to be 0-padded to 4 digits, string comparison is possible. Otherwise, you'll have issues. As things stand, it looks like your code was trying to compare a string (like an element from fastTrainReading) and a number (currentTime).

Just declare your array as strings:
var fastTrainReading = ['0943', '0957', '1006', '1013'];
And don't worry fastTrainReading[i] > currentTime will still work.
'100' > 99 == true

Related

Javascript - quick way to check if 10 variables are between 0 and 1?

I know there's probably an easy loop for this, but can't think of it.
I have 10 scores, and I need to validate them by making sure they are between 0 and 1 (plenty of decimals).
The input is pretty loose, so blank, null, alphanumeric values can be in there.
Right now I simply have
if (!(score1>=0 && score1<=1)){var result="error"} else
if (!(score2>=0 && score2<=1)){var result="error"} else
if (!(score3>=0 && score3<=1)){var result="error"} ...
Maybe not the most elegant formatting but -- there's got to be a way to loop through this, right?
Just use every MDN, and place your numbers in an array.
var score1 = 0.89;
var score2 = 0.75;
var score3 = 0.64;
var booleanResult = [score1,score2,score3].every(s => s >= 0 && s<= 1);
console.log(booleanResult);
This answer uses an arrow function:
Alternatively, this is an example of using every with a classic function callback
var score1 = 0.89;
var score2 = 0.75;
var score3 = 0.64;
var booleanResult = [score1,score2,score3].every(function(s){ return s >= 0 && s<= 1 });
console.log(booleanResult);
you could try something like this
var array = [var1, var2, varn ...];
for (let arr of array) {
if (typeof arr === 'number')
if (arr >= your condition)
... the rest of your code here
}
You can just create an array var numbersArray = [var1, var2, var3 ...] iterate through the array and check the if, you can create a "flag" variable with a boolean and if any of the numbers result in error then change the flag value and break the for...
That's it, pretty straightforward.
You can do it this way:
for (i = 1; i <= 10; i++)
{
if (!(window["score"+i.toString()]>=0 && window["score"+i.toString()]<=1)){var result="error"}
}
Here is a fiddle to prove the concept: https://jsfiddle.net/gL902rtu/1/
And as mentionned by #Rick Hitchcock, the score variable has to be global (see the fiddle for example)
Proof of concept:
score1 = 0.5;
score2 = 0.1;
score3 = 0.5;
score4 = 0.8;
score5 = 0.9;
score6 = 0.4;
score7 = 0.10;
score8 = 0.4;
score9 = 0.5;
score10 = 0.8;
result = "noerror";
for (i = 1; i <= 10; i++){
if (!(window["score"+i.toString()]>=0 && window["score"+i.toString()]<=1)){
result="error"
}
}
console.log(result);
Note that this would work with your code but the easiest way would be for sure to store your score in a array and loop trough it, it's pretty much what arrays are for.
You can have more information about array over here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
I would use a function for this, where the first argument is minimum, second is maximum, then the rest are numbers to check, then using .filter() to find invalid numbers:
function CheckRange(min, max) {
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments);
return args.slice(2).filter(function(x) {
return x < min || x > max;
}).length == 0;
}
return true;
}
console.log(CheckRange(0, 1, 0.25, '', null, 0.7, 0.12, 0.15));
In the above code empty or null are treated as valid, easy enough to disallow them if needed.
const scores = [0.1, 0.2, 0.3, 0.4, 1, 2, 3, 4, 5, 6];
scores.forEach(function(score){
// http://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
let isFloat = ( Number(score) === score && score % 1 !== 0 );
if (isFloat && (score > 0 && score < 1))
console.log("It's correct!");
});
Putting your scores into an array would be the best starting point. You can do this easily like:
var allScores = [score1, score2, score3];
Once you have an array, if you are targeting a platfrom with ES5 support check here then you can use the filter function of an array:
var errorScores = allScores.filter(function(s) {
return !(parseInt(s) >= 0 && parseInt(s) <= 1)
});
if (errorScores.length > 0) {
// Do some error handling.
}
Here is an example of this on code pen
Alternatively, if you can't use filter then you can do a loop like this:
for (var i = 0; i < allScores.length; i++) {
var score = allScores[i];
if (!(parseInt(score) >= 0 && parseInt(score) <= 1)) {
// Do some error handling.
document.write('something went wrong!');
}
}
Here is an example of this on code pen
Note the use of parseInt above to handle, null, '' and other text values. Invalid numbers will be parsed to NaN which will fail to meet the condition.
If you are using lodash, you can use
_.pluck(window, function(key, value) {}) and then check if key contains variable name and value is less than 10.
You can use
var i;
for (i = 0; i <= 10; i=i) { // i=i means do nothing
i++;
if( eval("score" + i + ">=0 && score" + i + "<=1") ) {
// do something
}
}
However, you should use some sort of type-checking; eval is considered unsafe in certain contexts.

What is the faster way to convert an object with property value: "HH:MM:SS" to string "N Minutes"?

I have hundred of objects with structure like
{
movieName: 'xyz',
time: '02:15:50'
timeAsText: null
}
I need to set timeAsText with a text as "136 minutes" based on property 'time'.
Seconds should be rounded up.
Could you point me out what could be the faster approach?
I tried this with two methods (DEMO); the first using map, and the second using a plain for...loop. As you can see from the demo the plain loop is considerably faster:
var out = [];
for (var i = 0, l = arr.length; i < l; i++) {
var obj = arr[i];
var time = obj.time.split(':').map(Number);
if (time[2] > 0) { time[1]++; }
obj.timeAsText = (time[0] * 60) + time[1] + ' minutes';
out.push(obj);
}
the best to do is probably that, and, seeing the numbers of similar answers, probably the only one.
-first, you use split(':') to make your string become a array of parseable string;
-then, parse the value to int. Use parseInt
at this time, you should have a array like that
[number_of_hours, number_of_minutes,number_of_second]
-then you just have to add the different values like
obj.timeAsText = array[0]*60+array[1]+Math.round(array[2]/60)+' minutes';
The full answer :
var arr=obj.time.split(':').forEach(function(entry){
entry=parseInt(entry);
});
obj.timeAsText= arr[0]*60+arr[1]+Math.round(array[2]/60)+" minutes";
Try this
var obj = {
movieName: 'xyz',
time: '02:15:50'
timeAsText: null
}
var a = obj.time.split(':'); // split it at the colons
var minutes = parseInt(+a[0]) * 60 + parseInt(+a[1]) + Math.round(parseInt(+a[2])/60);
obj.timeAsText = minutes + " minutes";
I don't know if it's the fastest, but it's the most easily readable one:
var test = {
movieName: 'xyz',
time: '02:15:50',
timeAsText: null
};
test.time.replace(/^(\d{2}):(\d{2}):(\d{2})$/, function(m, p1, p2, p3) {
// Multiplication and division implicitly converts p1 and p3 to numbers
return p1*60 + parseInt(p2) + Math.ceil(p3/60);
});

Small Straight (Yahtzee) Algorithm

I have created a working javascript function to check an array of 5 numbers for a small straight, in a Yahtzee game I'm making. I've tested it to no end and I'm confident it works 100% of the time, but it is also probably the worst algorithm of all time in terms of being efficient. Here is what it looks like:
function calcSmstraight() {
var sum = 0;
var r = new Array();
var r2 = new Array();
var counter = 0;
var temp;
var bool = false;
var bool2 = false;
r[0] = document.getElementById('setKeep1').value;
r[1] = document.getElementById('setKeep2').value;
r[2] = document.getElementById('setKeep3').value;
r[3] = document.getElementById('setKeep4').value;
r[4] = document.getElementById('setKeep5').value;
// Move non-duplicates to new array
r2[0] = r[0];
for(var i=0; i<r.length; i++) {
for(var j=0; j<r2.length; j++) {
if(r[i] == r2[j]) {
bool2 = true; // Already in new list
}
}
// Add to new list if not already in it
if(!bool2) {
r2.push(r[i]);
}
bool2 = false;
}
// Make sure list has at least 4 different numbers
if(r2.length >= 4) {
// Sort dice from least to greatest
while(counter < r2.length) {
if(r2[counter] > r2[counter+1]) {
temp = r2[counter];
r2[counter] = r2[counter+1];
r2[counter+1] = temp;
counter = 0;
} else {
counter++;
}
}
// Check if the dice are in order
if(((r2[0] == (r2[1]-1)) && (r2[1] == (r2[2]-1)) && (r2[2] == (r2[3]-1)))
|| ((r2[1] == (r2[2]-1)) && (r2[2] == (r2[3]-1)) && (r2[3] == (r2[4]-1)))) {
bool = true;
}
}
if(bool) {
// If small straight give 30 points
sum = 30;
}
return sum;
}
My strategy is to:
1) Remove duplicates by adding numbers to a new array as they occur
2) Make sure the new array is at least 4 in length (4 different numbers)
3) Sort the array from least to greatest
4) Check if the first 4 OR last 4 (if 5 in length) numbers are in order
My question:
Does anyone know a way that I can improve this method? It seems ridiculously terrible to me but I can't think of a better way to do this and it at least works.
Given that you're implementing a Yahtzee game you presumably need to test for other patterns beyond just small straights, so it would be better to create the array of values before calling the function so that you can use them in all tests, rather than getting the values from the DOM elements inside the small straight test.
Anyway, here's the first way that came to my mind to test for a small straight within an array representing the values of five six-sided dice:
// assume r is an array with the values from the dice
r.sort();
if (/1234|2345|3456/.test(r.join("").replace(/(.)\1/,"$1") {
// is a small straight
}
Note that you can sort an array of numbers using this code:
r2.sort(function(a,b){return a-b;});
...but in your case the values in the array are strings because they came from the .value attribute of DOM elements, so a default string sort will work with r2.sort(). Either way you don't need your own sort routine, because JavaScript provides one.
EDIT: If you assume that you can just put the five values as a string as above you can implement tests for all possible combinations as a big if/else like this:
r.sort();
r = r.join("");
if (/(.)\1{4}/.test(r)) {
alert("Five of a Kind");
} else if (/(.)\1{3}/.test(r)) {
alert("Four of a Kind");
} else if (/(.)\1{2}(.)\2|(.)\3(.)\4{2}/.test(r)) {
alert("Full House");
} else if (/(.)\1{2}/.test(r)) {
alert("Three of a Kind");
} else if (/1234|2345|3456/.test( r.replace(/(.)\1/,"$1") ) {
alert("Small Straight");
} // etc.
Demo: http://jsfiddle.net/4Qzfw/
Why don't you just have a six-element array of booleans indicating whether a number is present, then check 1-4, 2-5, and 3-6 for being all true? In pseudocode:
numFlags = array(6);
foreach(dice)
numFlags[die.value-1] = true;
if(numFlags[0] && numFlags[1] && numFlags[2] && numFlags[3]) return true
//Repeat for 1-4 and 2-5
return false
This wouldn't be a useful algorithm if you were using million-sided dice, but for six-siders there are only three possible small straights to check for, so it's simple and straightforward.
I do not play Yahtzee, but I do play cards, and it would appear the algorithm might be similar. This routine, written in ActionScript (my JavaScript is a bit rusty) has been compiled but not tested. It should accept 5 cards for input, and return a message for either straights greater than 3 cards or pairs or higher.
private function checkCards(card1:int,card2:int,card3:int,card4:int,card5:int):String
{
// Assumes that the 5 cards have a value between 0-12 (Ace-King)
//The key to the routine is using the card values as pointers into an array of possible card values.
var aryCardValues:Array = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
aryCardValues[card1] += 1;
aryCardValues[card1] += 1;
aryCardValues[card1] += 1;
aryCardValues[card1] += 1;
aryCardValues[card1] += 1;
var aryCardNames:Array = new Array("Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King");
var strOutMessage:String;
var intCardCount:int = 0;
var strSeperator:String;
var strHighCard:String;
for (var i:int = 0;i < aryCardValues.length;i++)
{
//Check for runs of three of a kind or greater.
if (aryCardValues[i] >= 2)
{
strOutMessage = strOutMessage + strSeperator + i + "-" + aryCardNames[i] + "s";
strSeperator = " & ";
}
//Check for values in a straight.
if (aryCardValues[i] > 0)
{
intCardCount++;
if (intCardCount > 3)strHighCard = aryCardNames[i];
}
else
{
if (intCardCount < 3)intCardCount = 0;
}
}
if (intCardCount > 3) strOutMessage = intCardCount + " run " + strHighCard + " High."
return strOutMessage;
}
It may not be as concise as the regular expressions used above, but it might be more readable and easily modified. One change that could be made is to pass in an array of cards rather than discrete variables for each card.

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.

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