0

I will be using coffeescript/javascript/jquery and I need to return true if a string contains all of my substrings.

So, lets say that I have an array of substrings 'my', 'dog', 'spot'. I need to return a true if my string is 'growing up my pet dog was named spot'. But I would need to return false if the string was 'I had a dog named spot'.

I am thinking there is a way to do this with a regular expression, but can't seem to figure it out?

Tom Rossi
  • 10,170
  • 5
  • 55
  • 85
  • 3
    Can you show us some of your code/what you have already tried? – rink.attendant.6 Aug 09 '13 at 13:14
  • 1
    do you care about case (e.g. would "my" match "My pet dog was named spot." ?) – SheetJS Aug 09 '13 at 13:19
  • _"I will be using..."_, sounds like you haven't even _tried_ anything... – Elias Van Ootegem Aug 09 '13 at 13:22
  • @EliasVanOotegem Geez. I'm sorry I couldn't figure it out! – Tom Rossi Aug 09 '13 at 14:09
  • @TomRossi: [Check the help center](http://stackoverflow.com/help): A good question contains code, showing what you've tried. It provides evidence of research efforts and is clear about the expected result, and what problems you're faced with. You've done none of all that. Nirk asked if the matching should be case-sensitive: no reply, you posted no code, nor mention any attempts. It's as if you expect us to do the work for you... – Elias Van Ootegem Aug 09 '13 at 14:12
  • @EliasVanOotegem Thanks for the lecture. Obviously it was clear enough that crazytrain figured it out in less than 10 minutes. – Tom Rossi Aug 09 '13 at 14:24
  • @TomRossi: As did I, I answered your question, too. But found myself writing a lot of `if`'s in the comment: (_"If the array of substrings isn't a given"_, _`'i'`//optional, to make matches case-insensitive_). Don't get all whingy about it, all I did was point out what was unclear about your question, and why your question was down-voted (PS: I didn't even down-vote it). rink.attendant said the same thing, and that comment got upvoted 3 times, so I'm not the only one who feels that way about questions like this – Elias Van Ootegem Aug 09 '13 at 14:26
  • @EliasVanOotegem Sorry, I couldnt figure out a way to do it without an ugly loop and thought maybe there was an elegant regular expression. CrazyTrains solution is perfect. I can figure out the details, just needed an answer to the exact question I posted which he did in spades. – Tom Rossi Aug 09 '13 at 14:40

5 Answers5

6
var mystring = "growing up my pet dog was named spot";
var words = ['my', 'dog', 'spot'];

var res = words.every(function(word) {
    return mystring.indexOf(word) !== -1;
});

If you want to reuse the function in various parts of your application, give it a name, and provide the string to be searched as the second argument, which makes it the this value.

function hasWordInString(word) {
    return this.indexOf(word) !== -1;
}

var res = words.every(hasWordInString, mystring);

The other nice thing about .every() is that it short-circuits if false is returned, so the search stops once a non-matching word is found, making it a little more efficient.


Force whole word matching

If you want to ensure that the matched string is a whole word to avoid "dog" matching "dogma" for example, you will need to make use of RegExp word boundaries:

function hasWordInString(word) {
    return this.match(new RegExp("\\b"+word+"\\b"))!=null;
}
var res = words.every(hasWordInString,mystring);
MDEV
  • 10,240
  • 1
  • 29
  • 49
  • 3
    I'm basically up-voting for introducing me to [`Array.every()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every). – David says reinstate Monica Aug 09 '13 at 13:20
  • Perfect! Love the Array.every() as well! – Tom Rossi Aug 09 '13 at 13:22
  • If this is going to be the accepted answer, it really needs to include the code in my answer which looks for words using regex word boundaries - as the example implies finding words, whereas indexOf wouldn't match that criteria – MDEV Aug 09 '13 at 14:29
  • @SmokeyPHP: It's a CW. –  Aug 09 '13 at 14:49
  • IE8 doesn't support Array.every()! Grrrrr! – Tom Rossi Aug 09 '13 at 18:28
  • 1
    @TomRossi: Correct, nor does it support `.indexOf()` on Arrays. IMO, you can make your life a bit easier if you load an IE8 polyfill. There are some very good projects available. This way you can fill in most of what's missing in IE8, and conditionally load the script so that other browsers don't need to download it. –  Aug 09 '13 at 18:31
1

An alternate method for the books:

var str1 = "growing up my pet dog was named spot";
var str2 = "I had a dog named spot";
var words = ['my','dog','spot'];
function str_match_array(str,array)
{
    var found = array.filter(function(part) { return str.indexOf(part)>-1; });
    //Or using regex and word boundaries:
    var found = array.filter(function(part) { return str.match(new RegExp("\\b"+part+"\\b"))!=null; });
    return (found.length == array.length);
}
str_match_array(str1,words);//true
str_match_array(str2,words);//false

Using the .every method with regex to assert word boundaries:

function str_match_array(str,arr)
{
    return arr.every(function(part) {
                return str.match(new RegExp("\\b"+part+"\\b"))!=null;
            }); 
}
var result = str_match_array(str1,words);//true
var result = str_match_array(str2,words);//false
MDEV
  • 10,240
  • 1
  • 29
  • 49
1

Right, if the array of substrings isn't a given:

words = words.forEach(function(word)
{
    return new RegExp(
        word.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),//escape
        'i'//optional, to make matches case-insensitive
    );
});
//for browsers that don't support forEach:
words = (function(words)
{//turn array of substrings into regex's
    for (var i=0;i<words.length;i++)
    {
        words[i] = new RegExp(
               words[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
               'i'
        );
    }
    return words;
}(words));

Then, to match any substring:

function checkAll(string, patterns)
{
    patterns.forEach(function(pattern)
    {//or for loop for older browsers...
        if (!pattern.test(string))
        {//no match found
            return false;
        }
    }
    return true;
}
checkAll('growing up my pet dog was named spot', words);//true
checkAll('growing up my pet DOG was named Spot', words);//true
checkAll('the quick brown fox jumps over the lazy dog', words);//false

I got the char escaping regex I'm using to escape strings I'm passing to the RegExp constructor from here.

Community
  • 1
  • 1
Elias Van Ootegem
  • 67,812
  • 9
  • 101
  • 138
0

You don't need regular expression for this - just use indexOf, check for each words, and return if any of the words was not found

var check_string = function(string, words) {
    var count = 0;
    for (var i in words) {
      if (string.indexOf(words[i]) === -1) {
         return false;
      }
    }
    return true;
}
Maxim Krizhanovsky
  • 24,757
  • 5
  • 49
  • 85
0
var ary=['my', 'dog', 'spot'];
var str="growing up my pet dog was named spot";
var temp="";

for(var i=0;i<ary.length;i++){

    temp=temp+".*(?:"+ary[i]+").*";

}

var regex= new RegExp(temp);
alert(regex.test(str));

http://jsfiddle.net/cgYTZ/