I do not understand why undefined appears in result. I use a question mark (\d+)?, it matches the previous element zero or one time:
// I want to match two cases with one regexp:
// "GBP 5 per hour" and "GBP 5 per 10 hours"
//
"GBP 5 per hour".match(/([a-z]{3}) (\d+(?:\.\d+)?) per\s?(\d+)?\s?(hours?|days?|minutes?)/im)
["GBP 5 per hour", "GBP", "5", undefined, "hour"] // actual result
["GBP 5 per hour", "GBP", "5", "hour"] // the result I'd like to get
How to get rid of that undefined?
The result will be the data (text) that is matched, if you are saying you want to match zero or one, and it matches zero then there is no data to return, and undefined is the result of that.
I would speculate that the design reason as to why the match is preserved is because it keeps the indexes consistent, so you can still access them as you would expect to. This way it enables you to effective test "was anything matched" by checking for undefined.
If you want to remove it from the array then you could use the filter function, for example:
arr = arr.filter(function(e){return e});
(Which I stole from here)
try
var x = ["GBP 5 per hour", "GBP", "5", undefined, "hour"];
var y = x.filter(Boolean);
as in Javascript any non-proper value is false that should help. Found it a few months ago written by Elad here
No simpler than
"GBP 5 per hour"
.match(/([a-z]{3}) (\d+(?:\.\d+)?) per\s?(\d+)?\s?(hours?|days?|minutes?)/im)
.filter(function(i){return typeof i != 'undefined'})
Since match will return an array, you can filter its elements with the filter method. The filter method can accept a callback (closure, function name as string, ...). Array elements are iterated and every element is passed to the callback function and is only accepted if the callback return value is equivalent to Boolean True
Hope it helps
The problematic part of your RegEx is:
per\s?(\d+)?\s?
Three possible solutions:
<script type="text/javascript">
//Quick & Dirty
var $text = "GBP 5 per hour";
var $arr = $text.match(/([a-z]{3}) (\d+(?:\.\d+)?) per ?(\d+)?\s?(hours?|days?|minutes?)/im);
console.log( $arr )
var $arrTmp = []
for( var $i = 0; $i < $arr.length; $i++ )
if( typeof $arr[$i] != 'undefined' )
$arrTmp.push( $arr[$i] )
$arr = $arrTmp;
console.log( $arr );
//Different approach
var $text = "GBP 5 per hour";
var $text1 = "GBP 5 per 10 hours";
var $regEx = /([a-z]{3}) (\d+(?:\.\d+)?) per(.*)(hours?|days?|minutes?)/im
var $arr = $text.match( $regEx );
var $arr1 = $text1.match( $regEx );
if( !isNaN( parseInt( $arr[3] ) ) )
$arr[3] = parseInt( $arr[3] );
else
$arr[3] = 1;
if( !isNaN( parseInt( $arr1[3] ) ) )
$arr1[3] = parseInt( $arr1[3] );
else
$arr1[3] = 1;
console.log( $arr1 );
console.log( $arr );
</script>
undefined represents the place where the last digit you try to match should be (per\s?(\d+)) when the digit exists.
To be coherent in any case, you should keep it, and maybe handle it as if it was a 1.
If you prefer an empty string, you can try this one :
"GBP 5 per hour".match(/([a-z]{3}) (\d+(?:\.\d+)?) per\s?([\d]*)\s?(hours?|days?|minutes?)/im)
I don't know if it's possible to directly get an array without it (I mean without filtering the array).
Related
I am trying to split this string down into sections:
2 h 3 12 s
From this I am trying to create a longer string such as:
00020312
DDHHMMSS
I am getting an error on line 21:
Cannot read property split of undefined
//calculate which ticket is the oldest begining
jQuery('.table-list-search tr').each(function(){
var downTime = jQuery(this).find('.downTime').text();
downTime = String(downTime);
var hasDays = downTime.split("d");
var hasHours = downTime.split("h");
var hasMins = downTime.split("m");
var hasSeconds = downTime.split("s");
if(hasDays[1] === undefined){
var downTimeD = downTime.split(" d")[0];
downTime = downTime.split(" d ")[1];
if(downTimeD <=9){
downTimeD = downTimeD.toString(downTimeD);
downTimeD = '0' + downTimeD;
};
}else{
var downTimeD = '00';
};
if(hasHours[1] === undefined){
var downTimeH = downTime.split(" h")[0];
downTime = downTime.split(" h ")[1];
if(downTimeH <=9){
downTimeH = downTimeH.toString(downTimeD);
downTimeH = '0' + downTimeH;
};
}
Your task can be done by applying a regular expression:
const rx=/(?:(\d+) *d *)?(?:(\d+) *h *)?(?:(\d+) *m *)?(?:(\d+) *s *)?/;
const fmt=s=>(s||'0').padStart(2,'0');
console.log('DDHHMMSS')
console.log( rx.exec('2 h 3 m 12 s').slice(1).map(fmt).join('') )
console.log( rx.exec('1d24m' ).slice(1).map(fmt).join('') )
The expression looks for (optional) groups of numbers with the letters 'd', 'h', 'm' or 's' behind them, qualifying each number in turn as "days", "hours", "minutes" and "seconds".
Debuggex Demo
The result is returned as an array. From this array only the elements 1 to 4 being used, as the 0-th element would be the complete matched string.
The whole job can also be packed into a single function like:
fmta=dt=>/(?:(\d+) *d *)?(?:(\d+) *h *)?(?:(\d+) *m *)?(?:(\d+) *s *)?/
.exec(dt).slice(1).map(s=>(s||'0').padStart(2,'0')).join('');
console.log(fmta('12d6h56m 45s')); // '12065645'
Where does downTime come from? The error you're getting means that the variable does not exist. It might be a typo somewhere.
Edit - this was posted before the question contained a full code snippet, but the answer stands - if you get such an error, it usually is because the variable is not defined.
Edit 2 - There are a number of weird things in the logic. First if(hasDays[1] === undefined) essentially translates to "downTime has no 'd' in it", so all further attempts to break on 'd' do not split the string. So downTime = downTime.split(" d ")[1]; would never yield anything - downTime has no d's, so it can't be split on them.
Then there' a corner case in the line downTime = downTime.split(" d ")[1]; (and the similar one below). You're splitting on " d "while the above splits are on " d" and "d".
In summary, you would like to change if(hasDays[1] === undefined) to if(hasDays[1] !== undefined) and always split on "d" with no extra spaces, and the same for the things below.
Trying to bitwise OR a group of values and wrote a some test code that doesn't return what I would expect ( old C programmer ). My test code:
// take 3 values from string ( 1,2,3 ) and OR them together
var values="012345678"; // sample characters
var val=0; // int to place single ascii value
var bin=0; // binary value after offset
var total=0; // cumulative total
var pos=1; //where to start pulling characters
// take 3 values from string ( 1,2,3 ) and OR them together
for(let i=0;i<3;i++){
var singleVal=values[pos++];
val=Number(singleVal.charCodeAt(0));
bin=val-48; // position offset by ascii "0" = 48
total|=bin;
}
// Result should be 7 but always returns the last singleVal
console.log("total: "+total);
Result should be 7 but always returns the last singleVal
with bitwise or the result of 1|2|3 is 3, not 7 (01|10|11 = 11).
If you loop until 7 then the result would be 7:
for(let i=0;i<7;i++){
I saw one of the masters doing this:
var example = '';
Then later he continued with this:
example += '<div>just a div</div>';
I wanna know if there's any difference from doing this:
var example;
example += '<div>just a div</div>';
I don't really know if by doing the second method I'm doing wrong and I have to code like shown if the first example.
Updated!
Thank you so much for your answers, Ok I got it I need to define my variable to be able to work woth it, but then another question came... This master also is doing this:
var guess;
and then he does:
guess += myfunction( upper );
where myfunction was declared as follows:
function myFunction( upper ){
return Math.floor( Math.random() * upper ) + 1;
}
So, why here is different? Can any of you answer this please?
Thank you!
Second update!
Again Thanks!
I decided to post the whole code the JS master was doing, at this point I don't understand, so probably you'll be able to clear my doubts.
var randomNumber = myFunction( 10 );
var guess;
var attempts = 0;
var answer = false;
function myFunction( upper ){
return Math.floor( Math.random() * upper ) + 1;
}
do{
guess = prompt( "I created a number from 1 till 10, can you guess it?");
attempts += 1;
if( parseInt( guess ) === randomNumber ){
answer = true;
}
}while( ! answer )
document.write( "Took you " + attempts + " attempts to guess the number " + randomNumber);
Please have a look at:
var guess;
and how later is being declared, so why here works perfectly but in my first example I have to put the '' when declaring my variable?
I hope my question is clear enough for you!
Thank you for your time and patient!
When you do:
var example;
example += '<div>just a div</div>';
You end up with:
`"undefined<div>just a div</div>"`
This is because when you don't initialize a variable, it is undefined, which can be converted to a sensible string "undefined" when you try to add it to another string.
When you do:
var guess;
guess += myfunction( upper );
function myFunction( upper ){
return Math.floor( Math.random() * upper ) + 1;
}
You are adding a number to undefined. This results in NaN (not a number) because undefined cannot be converted into a sensible number.
You can check this yourself next time by opening up your browser's developer tools and running the code in the console.
Edit:
When you do:
var guess;
guess = prompt( "I created a number from 1 till 10, can you guess it?");
There's no issue because you are simply assigning a string to the guess variable. In the previous examples you were adding something to a variable, which means if they are different types then JavaScript has to try to do something sensible.
If you don't initialize your variable it has a value of undefined.
In your last example, you are really saying example = undefined + '<div>just a div</div>' and undefined will be converted to a string and output that way. Probably not what you want.
In general it is a good idea to initialize your variables before you use them which is why var example = '' is preferable in this case.
var myvar
myvar += 'asdf'
console.log(myvar) // prints undefinedasdf
var othervar = ''
othervar += 'sdfasdf'
console.log(othervar) // prints sdfasdf
If you don't initialize the variable then it will be undefined
Appending to undefined object doesn't help.
var example = '';
Here you are initializing an empty string to the variable and therefore appending a string to another string will give the desired output of string concatenation.
Output:
"undefined<div>just a div</div>"
"<div>just a div</div>"
Yes there is a difference the first snipet from the master creates a variable example and gives it a default value, the second statement concatinates the value with 'just a div'
.Your code has an error as it is adding a value to a non-existed value as variable example has no default value.
I have a pricing table, I want to convert the data as shown in below.
Is there a specific way to do it other than doing mod and having a if condition
Original input = Output I needed
123.0 = 123
22.2 = 22.2
22.21 = 22.21
This is for javascript not Java.
Just do a toString() to get rid of trailling zeroes after decimal like this
var n = 123.0;
n = parseFloat(n.toString()) //outputs 123
make a method out of it
function removeTraillingZeroes( n ){ return parseFloat(n.toString()) }
removeTraillingZeroes( 123.3430 ); //outputs 123.343
removeTraillingZeroes( 123.330 ); //outputs 123.33
Note - You will need to assign the value back to n, if you want to use the same variable.
var n = 123.0;
n = removeTraillingZeroes( n ); //outputs 123
console.log(n);
Just return the values!
var array = [123.0, 22.2, 22.21];
document.write(array.join('<br>'));
I have a string that looks like "(3) New stuff" where 3 can be any number.
I would like to add or subtract to this number.
I figured out the following way:
var thenumber = string.match((/\d+/));
thenumber++;
string = string.replace(/\(\d+\)/ ,'('+ thenumber +')');
Is there a more elegant way to do it?
Another way:
string = string.replace(/\((\d+)\)/ , function($0, $1) { return "(" + (parseInt($1, 10) + 1) + ")"; });
I believe Gumbo was on the right track
"(42) plus (1)".replace(/\((\d+)\)/g, function(a,n){ return "("+ (+n+1) +")"; });
Short of extending the String object, it looks good to me.
String.prototype.incrementNumber = function () {
var thenumber = string.match((/\d+/));
thenumber++;
return this.replace(/\(\d+\)/ ,'('+ thenumber +')');
}
Usage would then be:
alert("(2) New Stuff".incrementNumber());
I believe your method is the best elegant you can have for following reasons:
since the input is not a "clean" number, you do need to involve some sort of string parser. Using regular expressions is the very code-efficient method to do it
by looking at the code, it's clear what it does
short of wrapping this into a function, I don't think there's much more to be done
As galets says, I don't think your solution is a bad one but here is a function that will add a specified value to a number in a specified position in a string.
var str = "fluff (3) stringy 9 and 14 other things";
function stringIncrement( str, inc, start ) {
start = start || 0;
var count = 0;
return str.replace( /(\d+)/g, function() {
if( count++ == start ) {
return(
arguments[0]
.substr( RegExp.lastIndex )
.replace( /\d+/, parseInt(arguments[1])+inc )
);
} else {
return arguments[0];
}
})
}
// fluff (6) stringy 9 and 14 other things :: 3 is added to the first number
alert( stringIncrement(str, 3, 0) );
// fluff (3) stringy 6 and 14 other things :: -3 is added to the second number
alert( stringIncrement(str, -3, 1) );
// fluff (3) stringy 9 and 24 other things :: 10 is added to the third number
alert( stringIncrement(str, 10, 2) );