I have a function that filter a food list and returns a fruit list.
The expected result is: ["apple", "banana", "watermelon"]
but the next code don't push watermelon
in the array.
const foodList = ["apple", "soap", "banana", "watermelon", "pizza"];
function getFruits(foodList) {
const fruitRGX = /apple|banana|watermelon/g;
const fruitList = [];
for (const food of foodList) {
if (!fruitRGX.test(food)) continue;
fruitList.push(food);
}
return fruitList;
}
const fruits = getFruits(foodList);
const expect = ["apple", "banana", "watermelon"];
console.log({ fruits, expect });
// output:
// {
// fruits: [ "apple", "banana" ],
// expect: [ "apple", "banana", "watermelon" ]
// }
If I remove the g
flag in the fruitRGX
or I move the constant declaration inside the for loop then fruits
is equal to expect
.
Can someone explain what happening?
Edit
I already get the answer since the first comment, see my reply or Ben Calder's comment if you want see a quick explain about this problem.
Top comments (8)
This had me scratching my head for a few minutes - I don't typically use
RegExp.test
...So it looks like the problem is caused by this documented behaviour:
So since watermelon follows banana - which returned true - the stored lastIndex influences the point from which the next test is made and the match fails. The solution is simple: remove the
g
flag. You'd only use that in a regex if you were searching for multiple matches in the same string (which would go some way to explaining the exhibited behaviour).Oh - and one suggestion in terms of naming - I wouldn't use
food
in your iterator or array name:It might seem pedantic; but at this point you're testing whether they are food; so I'd use generic terms
item
anditemList
.That's true. I have explained this weird behavior in my this article
I already found that document since the first comment. Anyway, I edited the post mentioning your comment. Thank you.
you can do like this:
I think if you use
match(regex)
instead of test() is better.and you can use
array.forEach()
instead offor()
for better readability!Thanks for the advise, what I really need is to know what happened with my code.
What is the reason for not output watermelon?
But somehow your code is very helpful, you used
match
and it worked well so my question has changed to whytest
don't worked butmatch
yes?. This time I found the info that I want:The
RegEx
object has a property calledlastIndex
updated withtest
method, that property don't reset whentest
returnstrue
. If the same regex is used again then can happen what happened with my code.@ghaerdi I have explained this weird behavior of test method in my this article.
Or better yet, a pure function: