简体   繁体   中英

How to get rid of “undefined” in regexp result?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM