const xo = s => (s.match(/x/gi) || ).length == (s.match(/o/gi) || ).length;
Oh look, you had already come up with the same idea as I did!
Yes. Although mine looks a bit uglier because I ran into an issue: if the string doesn't have Xs or Os, the result of match is null so it fails when trying to do .length (test checkXO("zpzpzpp") on your code).
I had to add the fallback into empty array for those cases. But I feel like there has to be a cleaner way of doing the same thing.
Yeah, I found the same issue when I tried to solve it in Codewars. So I had to do the same. Looking through other people's solutions, there's one that I find interesting that uses split() instead of a regular expression. Something like this:
const xo = str => str.toLowerCase().split('x').length == str.toLowerCase().split('y').length
The split approach is interesting. I was playing with different options, but not with this. Also, I found that using toLowerCase() made the code considerably slower, it works considerably faster if you use a regular expression in the split:
const xo6 = str => str.split(/x/i).length == str.split(/o/i).length;
I think this is my favourite solution. I hadn't checked its speed, but I thought that toLowerCase() probably didn't make it any smoother than returning an empty array if there are no matches.
I checked different solutions with jsperf and this was the second fastest by a little (but results may vary.)
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.