JS regex match returning null - javascript

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.

Related

How do I convert my stopwatch time to a time?

The question may be a little confusing so let me clarify a bit more. I am doing a stop watch so when you start then stop it logs your time. I put that time into an array. When I try to do things like Math.min(array) or Math.max(array) I got NaN (not a number). The stop watch time for example is like 00:00:15.91. Obviously that doesn’t register as a legit number, is there a way to get around this?
In more simpler words: I put a “time” (like 00:00:15.91) into an array, is there a way to still retrieve the largest number or smallest number?
I’m doing this all in javascript, no libraries.
Note: I believe I don’t need to show my code for this, but if you need any, I will be happy to provide it.
else{
let displayTime = displayHours + ":" + displayMinutes + ":" + displaySeconds + "." + displayMilliseconds;
let intTime = displayHours + displayMinutes + displaySeconds + displayMilliseconds;
let times = document.getElementById("times");
window.clearInterval(interval);
status = "stopped";
if (status = "stopped") {
times.innerHTML += displayTime + "<img src='https://img.icons8.com/windows/32/000000/xbox-x.png'/><br/>";
allTimes.push(Number(intTime));
if (allTimes.length == "0") {
document.getElementById("bestTime").innerHTML = "none";
document.getElementById("worstTime").innerHTML = "none";
document.getElementById("average").innerHTML = "none";
document.getElementById("stats").innerHTML = "none";
}
if (allTimes.length != "0") {
document.getElementById("bestTime").innerHTML = Math.min(...allTimes);
}
}
}
edit: I added my code
You can find min and max values ​​by comparing string values. Is type conversion necessary?
const list = ['00:00:23.90', '01:00:00.00', '00:00:23.89', '00:01:00.00']
list.sort()
const min = list(0) // -> "00:00:23.89"
const max = list(list.length-1) // -> "01:00:00.00"

Milliseconds in Lap Time Average dropping the Zero in Tenths place

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

Regex sometimes returning null in Javascript

While using regex to match values inside of a formula string I found this issue that regex would return null even though there is a match.
var formula = "round((DATAtotal_sq_ft * .6) + (QTY16 * 4) + (QTY17 * 2) + QTY18 + QTY15 + QTY12 * 18 / 3000, 1)";
const qtyRegex = /(QTY)(\d*)|(LEN)(\d*)|(DATA)([a-zA-Z_-|\d]*)/gm;
let m;
while ((m = qtyRegex.exec(formula)) !== null) {
var val = 0; // Here is irrelevant code that gets the value
formula = formula.replace(m[0], val);
}
console.log(formula);
In the above snippet you can see the result that a couple of the values don't get replaced but at the same time all of them get detected by
regex101 https://regex101.com/r/WTpvFq/1. For some reason I cant seem to narrow down what I'm doing wrong even after reading a number of different answers to similar problems.
I could use a workaround and use formula.match(qtyRegex) but I am really certain it's just an error in the Regex so I'd prefer properly fixing it instead of plastering it with a patch.
Instead of a while loop you can directly replace using the RegExp with the replacer callback of String.replace like this:
formula = formula.replace(qtyRegex, replacer)
// take a look at the docs I've linked above for an explanation of these params
function replacer(match, p1, p2, ..., offset, string) {
let calculatedValue = 0 // perform your irrelevant code that gets the value here
return calculatedValue
}
When you use the g modifier in a regexp, it remembers the position in the string where it last matched, and subsequent matches start from that position. But your code is replacing the match with a shorter string, so the remembered position may be past the beginning of the next match, and it doesn't find it.
Get rid of the g modifier and it will search from the beginning each time.
var formula = "round((DATAtotal_sq_ft * .6) + (QTY16 * 4) + (QTY17 * 2) + QTY18 + QTY15 + QTY12 * 18 / 3000, 1)";
const qtyRegex = /(QTY)(\d*)|(LEN)(\d*)|(DATA)([a-zA-Z_-|\d]*)/m;
let m;
while ((m = qtyRegex.exec(formula)) !== null) {
var val = 0; // Here is irrelevant code that gets the value
formula = formula.replace(m[0], val);
}
console.log(formula);

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;

JavaScript format number to day with always 3 digits [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I create a Zerofilled value using JavaScript?
I have to output a day number that must always have 3 digits. Instead of 3 it must write 003, instead of 12 it must write 012. If it is greater than 100 output it without formatting.
I wonder if there's a regex that I could use or some quick in-line script, or I must create a function that should do that and return the result. Thanks!
How about:
zeroFilled = ('000' + x).substr(-3)
For arbitrary width:
zeroFilled = (new Array(width).join('0') + x).substr(-width)
As per comments, this seems more accurate:
lpad = function(s, width, char) {
return (s.length >= width) ? s : (new Array(width).join(char) + s).slice(-width);
}
I found an elegant solution by Samuel Mullen on his blog. I simply optimized the zeroes creation.
function lpad(value, padding) {
var zeroes = new Array(padding+1).join("0");
return (zeroes + value).slice(-padding);
}
Usage: lpad(12, 3) results in "012"
You can do this...
("00" + day).slice(-3)
It'll prepend the zeros, and then .slice() will always give you the last 3 values of the string.
Here is a simple function that pads a number with zeroes to a certain width:
function zeroFill(number, width) {
width -= number.toString().length;
if(width > 0) {
return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number;
}
return number + ""; // always return a string
}
(from How can I pad a value with leading zeros?)
Since the original answer did not explain how the function works I'll do it here.
width initially contains the total length you want, so width - number_of_digits is the number of padding chars necessary.
new Array(len + 1).join(str) repeats str len times.
The regex is used to add an additional padding zero in case of a number containing a decimal point since the point was also included in the number_of_digits determined using number.toString().length
One possible solution:
​while ((val+"").length < 3​) {
val = "0" + val;
}
DEMO: http://jsfiddle.net/WfXVn/
I would write the following function:
var pad = function(n, length) {
var str = "" + n;
if(str.length < length) str = new Array(length - str.length).join("0") + str;
return str;
};

Categories

Resources