Match using predicate function in JavaScript

Viewed 459

Notice: This is my first question on StackOverflow (although I've answered before). If you think I haven't clarified something, feel free to tell me in the comments.

You may have heard of the String.prototype.match() function in JavaScript, which searches a string for a match against a regular expression, and returns the matches, as an Array object. Here's an example:

var str = "(list 1 2 foo (list nice 3 56 989 asdasdas))"
console.log(str.match(/\d+/g)) //=>["1", "2", "3", "56", "989"]

However, I need a match-like method that inputs a function in JavaScript. This input function would take in a substring of the original string, and output a boolean telling if the substring is a valid match or not. Here's an example of the intended behavior

    function standardFunc(substr) {
       return parseFloat(substr) !== NaN;
    }

    var str = "(list 1 2 foo (list nice 3 56 989 asdasdas))"
    console.log(str.match(standardFunc)) //=>["1", "2", "3", "56", "989"]

Is there an easy way to emulate this behavior in JavaScript?

2 Answers

If you can set or somehow identify the boundaries of which sorts of substrings get matched, it's possible. For example, here, every match looks to begin and end at a word boundary:

function standardFunc(str) {
   return !Number.isNaN(parseFloat(str))
}

const str = "(list 1 2 foo (list nice 3 56 989 asdasdas))";
for (const match of str.matchAll(/\b.+?\b/g)) {
  if (standardFunc(match[0])) {
    console.log(match[0]);
  }
}

Note you'll need to use Number.isNaN instead of using !== NaN.

If you're not looking for a general solution, but just a solution to this particular problem, solve this with a regex alone. Match digits followed by an optional decimal point and more digits:

function standardFunc(str) {
   return !Number.isNaN(parseFloat(str))
}

const str = "123.03 (list 1 2 foo (list nice 3 56 989 asdasdas))";
console.log(
  str.match(/\d+(?:\.\d+)?/g)
);

I would use the Array.prototype.filter method after converting the string to an array:

var stg = "(list 1 2 foo (list nice 3 56 989 asdasdas))";

var stgAsArray = stg.split(' ');

var numbersFromString = stgAsArray.filter(word => !Number.isNaN(parseFloat(word)));

console.log(numbersFromString)

console.log(numbersFromString.join(' '));

Related