3

I have an object with strings properties I want to compare to multiple user inputs using case insensitivity. My goal is to match input strings to object strings to increment the associated value by 1 (if it's a match).

var objArr = [
    {"O": 0},
    {"foo": 0},
    {"faa": 0},
    {"A": 0}
];

Everything is working smoothly except for the case insensitivity. The RegExp method I used just looks for one letter instead of the whole word. I'm probably not using the right syntax, but I can't find results on google which explain the /i flag along with a variable. My closest try was :

var re = new RegExp(b, "i"); //problem here 
if (allinputs[i].value.match(re)) { //and here

This code indeed allows case insensitivity but it doesn't look for the whole object property string and stops for letters. For exemple typing "foo" will result in a match to "O" because it contains the letter "O", and the property "O" is before "foo". Accordingly, typing "faa" matches to "faa" and not "A", because "faa" is before "A" in the objects array. Strings that don't exist in my object like "asfo" will still be matched to "O" because of the one common letter.

Is there a way to search for the whole property string with case insensivity using the regExp /i flag ? I want to avoid using .toUpperCase() or .toLowerCase() methods if possible.

Fiddle here : https://jsfiddle.net/Lau1989/b39Luhcu/

Thanks for your help

Lau
  • 179
  • 2
  • 4
  • 13

2 Answers2

3

To check that a regex matches the entire string, you can use the assert beginning character (^) and assert end ($).

For example, hello matches e but not ^e$.

For your code, just prepend ^ to the regex and append $:

var re = new RegExp("^" + b + "$", "i");

fiddle

Edit: Some characters have special meanings in regexes (^, $, \, ., *, etc). If you need to use any of these characters, they should be escaped with a \. To do this, you can use this simple replace:

str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");

So, your regex will end up being

new RegExp("^" + b.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + "$", "i");

See this question for more about escaping a regex.


You could also just convert the two strings to lowercase and then compare them directly. This will allow you to use special characters as well.

if (stringA.toLowerCase() == stringB.toLowerCase())) {
    ...
}
Community
  • 1
  • 1
3ocene
  • 2,102
  • 1
  • 15
  • 30
  • Thanks, your first solution works like a charm. Having one last problem though : I'm trying to support the '+' and '()' characters detection while ignoring the '/' character. I tried to add '\.' to the regex but it doesn't seem to work. Any idea of how I shoud do that ? https://jsfiddle.net/Lau1989/auue3xb3/2/ – Lau Oct 09 '16 at 16:58
  • Thank you so much. Complex regex like this one are still a bit confusing to me so I'll take some time to better understand how you "build" them. Your solution works perfectly however. – Lau Oct 09 '16 at 23:36
  • Honestly, in this scenario you're better off converting to lowercase and checking that the strings match (second part of my answer). The only reason to use regexes is if you want to use those special characters that are now being filtered out. – 3ocene Oct 11 '16 at 04:29
2

Your approach was almost right, but you need limitate your regular expression to avoid an any match using ^ (start of string) and $ (end of string).

Here is a code that I made that may fit to your need:

function process() {

var allinputs = document.querySelectorAll('input[type="text"]');
var list = new Array();
var input = "";

objArr.map(function(value, index, array){ list.push(Object.keys(value))})

for(var i = 0; i < allinputs.length; i++)
{
     input = allinputs[i];
     if(input.value)
     {
          list.map(function( item, index, array ) {
              var re = new RegExp("^"+input.value+"$", "i");
              if(item.toString().match(re))
              {
                  allinputs[i].value = "1";
                  objArr[index][item] += 1;
          allinputs[i].style.backgroundColor = "lime";
                  document.getElementById('output').innerHTML += item + " : " + objArr[index][item] + "<br />";
               }
         });
     }
  }

}

The first thing here is create a list of keys from your objArr, so we can access the key names easily to match with what you type

  objArr.map(function(value, index, array){ list.push(Object.keys(value))})

Then the logic stills the same as you already did, a for loop in all inputs. The difference is that the match will occur on list array instead of the objArr. As the index sequence of list and objArr are the same, it's possible to access the object value to increment.

I used the .map() function in the list array, bit it's also possible use a for loop if you prefer, both method will work.

I hope this help you!

Fabricio
  • 76
  • 3
  • Thanks a lot for teaching me a new approach to deal with this problem. I'm still struggling finding to correct syntax to support the '+' and '()' characters detection while ignoring the '/' character. Any idea or tutorial I might read ? Thanks again for your help – Lau Oct 09 '16 at 17:02
  • There are many explanations over the internet about RegEx, you can start see https://regexone.com. It's hard to explain about the () and + in RegEx, but let's say the () will hekp you to group your match patterns, and the + signal means that "one or more times" the match that come previous of it. For example: (a|b)+, you can, literally read this sentence as: a or b one or more times, in other words, any pattern that have one or more a's or b's will match with is RegEx. Don't confuse the + signal in JS that means a string concatenation. I hope this helps your to learn more about RegEx. – Fabricio Oct 11 '16 at 00:54