2

I am trying to find if a value stored in dynamic variable is inside of an array while ignoring case and not using to .toLowerCase() or upper.

What I have that works is:

if ($scope.favoriteItems.indexOf(item.name.toLowerCase()) === -1) {

I want something like using regex if (item.name 'no matter case is in $scope.favoriteItems)

BrTkCa
  • 4,703
  • 3
  • 24
  • 45
RooksStrife
  • 1,647
  • 3
  • 22
  • 54
  • 1
    Why does what you have not work for you? – VLAZ Oct 28 '16 at 18:19
  • @vlaz I want to use regex and I don't know how to do it with a variable in an if statement. – RooksStrife Oct 28 '16 at 18:32
  • well, the answer to _that_ particular question is to simply use `regex.test(string)` which returns a boolean. However, I am not sure if that's really the solution you are after, here. – VLAZ Oct 28 '16 at 18:36

2 Answers2

6

You could do something like this:

if ($scope.favoriteItems.some(item => (new RegExp(item.name, 'i')).test(item))) {
  // do something
}

Basically, to create a RegExp with a variable, you can new RegExp(), and give it the expression you want as the first parameter, and any flags as the second.

So, something like:

var name = 'abc';
new RegExp(name, 'i');

turns into:

/abc/i

var name = 'abc';
console.log(new RegExp(name, 'i'));

The Array.prototype.some function loops through each item in an array and keeps going until one returns true. In this case, we keep looping until one of them matches our regexp (meaning it's in the array) and then we stop.

That said, unless item.name is going to be something that isn't just a string match, using a regex test is massive overkill and you'd be better off sticking with what you have.

samanime
  • 25,408
  • 15
  • 90
  • 139
  • 1
    `using a regex test is massive overkill and you'd be better off sticking with what you have` to add to that, a regex could be DANGEROUS! Any meta characters in it will be interpreted as regex, so `.` will match anything, `*` will repeat, etc. This means that you can flag false positives if the new pattern matches something it shouldn't (`a.b` will match `AZB`), or it could lead to the code throwing an error with invalid regex (`*`). It's a massive can of worms for something as simple as this problem, as presented. Unless there is a particular reason for regex, I'd avoid it. – VLAZ Oct 28 '16 at 19:19
  • Indeed. You would have to implement some sort of escape to deal with it properly: http://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript – samanime Oct 28 '16 at 19:21
  • When you need to escape a regex, because you decided to use a regex to do a case insensitve search in an array, then I'd suggest you don't need a regex. Considering how simple lower/uppercasing both variables is, and how much less consideration it requires, I struggle to think of why one should even consider the regex. – VLAZ Oct 28 '16 at 19:42
  • I do not disagree in the slightest. I'm just saying, if there is some valid reason you must use regex like this, beyond the description we were given, then you'd want to escape it. However, for the condition described in the original question: yes, do not use regex. No point, overkill, slow and dangerous. – samanime Oct 28 '16 at 19:44
0

For ES5 it should be

var isFavourite = $scope.favoriteItems.some(function (favoriteItem) {
  return favoriteItem.toLowerCase() === item.name.toLowerCase();
});

For fully matched strings toLowerCase is preferred and fastest way to do case-insensitive comparison. There's no good reason to use regexp in this case. It would require to use additional function for sting escaping, for example escape-string-regexp:

var ITEM_REGEXP = new RegExp('^' + escapeStringRegexp(item.name) + '$', 'i');
var isFavourite = $scope.favoriteItems.some(function (favoriteItem) {
  return ITEM_REGEXP.test(favoriteItem);
});
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • There are minor improvement that can be done for for the first `isFavourite` but aren't really important enough to add to the answer (hence, just a comment): 1) using `.toLocaleLowerCase()` will be a bit more reliable in international context as, in some cases, the result would be _correct_, whereas `.toLowerCase()` won't be 2) the lookup value needs to be lowercased once, rather than every time. Might be a micro-optimisation, though – VLAZ Oct 28 '16 at 21:45
  • @vlaz That's true, thanks for the useful comment. – Estus Flask Oct 28 '16 at 21:54