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
?
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
?
- Look at my example below for filtering an array values with a callback function. In this example, the callback tests on the type of the element passed and accepts rejects undefined elements. Hope it helps – php-dev Commented Jan 21, 2014 at 12:09
5 Answers
Reset to default 3The 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).