1

I am trying to determine if a CSV string contains a specific number (also String), in this case the number 3. I have wrote some script to attempt this but the result always returns null. The regex works when using an online testing tool, however not when utilized via script. Can anyone determine what I'm missing?

Here is my code:

var csv = ["1,25,3","3", "1", "1,9,10", "2,4,5,6,7,11,33,3", "2,1,2,12,15,27"];

function contains(param){
    var regex = /(,)?\D[3]\D(,)?/g;
    return param.match(regex);
}

for(var i = 0; i < csv.length; i++){
  console.log(contains(csv[i]));
}

Or if you prefer: JsFiddle

4
  • Anything in parenthesis is used to catch the pattern.. I am not sure why you are trying to capture the commas... Commented Dec 9, 2012 at 19:23
  • I need to use a look ahead to make sure its not something that contains a 3 such as 232. This may not be the right approach just my attempt. Commented Dec 9, 2012 at 19:30
  • 1
    Why regex instead of .split().indexOf()? Commented Dec 9, 2012 at 19:31
  • @SalmanA Thats a great point, I just didn't think of doing that. Commented Dec 9, 2012 at 19:32

1 Answer 1

4

The problem is that your pattern requires a character (\D) before and after your 3. Since all 3s in your example are at the end of the string the second \D can never match. What you want is probably something like this:

var regex = /(?:^|\D)3(?!\d)/;

For the end of the string we use negative lookahead. That asserts that there is no digit. This is better than asserting that there is a non-digit character (because it works for the end of the string, too). Ideally, we would use the same for the beginning, but that is not supported by JavaScript. So we say, either we have the beginning of the string or a non-digit character. In fact (as Brad Koch pointed out), in this specific case, both conditions constitute a word boundary (a position between a character in [a-zA-Z0-9_] and one that is not or an end of the string). So you can simply use:

var regex = /\b3\b/;

However, if your input can include other characters than digits and commas (e.g. 1,text,2,a3b,somemoretext), none of these approaches are sufficient. Instead you need to check for commas explicitly:

var regex = /(?:^|,)3(?![^,])/;

Also, since you don't need the actual match, but only want to know whether there is a match, you can use test instead:

return regex.test(param);

This will give you a boolean instead of an array (which probably also makes is marginally more efficient).

Sign up to request clarification or add additional context in comments.

5 Comments

Can't you just use the word boundary /\b3\b/ anchor? Seems much simpler to me.
in the former case you are right. if other contents (like 3b) are allowed no. but good catch, I'll add it
@m.buettner Works perfect. One follow up question though, what does the : do in the expression?
@KevinBowersox ?: suppresses capturing. You don't want to refer to what was matched with (^|\D) later on (which you could if you wrote it like this and captured the submatch). Hence, you suppress the capturing which is generally good practice to get used to, because it can make an actual performance difference in more complex patterns.
@m.buettner Makes perfect sense. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.