1

Hello I have a JSON database where I need to match user input with keywords. I have had success with this except for one special case. Basically if a user inputs "icecream", there should be a match with the keyword or string "ice cream".

I tried deleting the whitespace in "ice cream" to making it "icecream" but it then negates alot of other matches such as "ice cream cone" which turns into "icecreamcone". Is there a regular expression that would work in this case?

var input = new RegExp("icecream", "i");
var keywords = "ice cream, ice cream cone, plastic container lid";

if (keywords.search(input) != -1) {

//do Something

}

It should find a match between "icecream" and "ice cream" also if I was to search up "plastic lid" instead of "plastic container lid" that should also find a match. Any help is greatly appreciated. Ultimately I am looking for a solution that would be able to tackle all situations, not just "ice cream" vs "icecream" specifically.

1
  • Why not add "icecream" to the list of keywords? for the latter case, you need a mechanism with history - that you do not have in regexp. You may consider gradual search. Break your input into "word's ( separated by white space) and perform search on each of the words and decide according to the messages Commented Jan 21, 2019 at 17:35

5 Answers 5

2

Tl;dr

var input = new RegExp('icecream'.split('').join('(\\s)*').concat('|icecream'), 'i');
var keywords = "ice cream, ice cream cone, plastic container lid";

if (keywords.search(input) != -1) {

//do Something

}

Full answer:

To answer your question I proposed the following method:

function makeRegEx(input) {
  // The regex for an optional whitespace.
  let glueRegex = '(\\s)*';

  // Transform the string into an array of characters.
  let splittedString = input.split('');

  // Join the characters together, with the optional whitespace inbetween.
  let joinedString = splittedString.join(glueRegex)

  // Add the actual input as well, in case it is an exact match.
  joinedString += '|' + input;

  // Make a new regex made out of the joined string.
  // The 'i' indicates that the regex is case insensitive.
  return new RegExp(joinedString, 'i');
}

This will create a new RegEx that places an optional space between each character.

That means that with a given string icecream, you end up with a RegEx that looks like this:

/i(\s)*c(\s)*e(\s)*c(\s)*r(\s)*e(\s)*a(\s)*m/i

This regex will match on all the following cases:

  • i cecream
  • ic ecream
  • ice cream <= This is yours!
  • icec ream
  • icecr eam
  • icecre am
  • icecrea m
  • icecream

The whole method can also be shortened to this:

let input = new RegExp(input.split('').join('(\\s)*').concat(`|${input}`), 'i');

It is pretty short, but also pretty unreadable.


Integrated into your code it looks like this:

function makeRegEx(input) {
  // The regex for an optional whitespace.
  let glueRegex = '(\\s)*';

  // Transform the string into an array of characters.
  let splittedString = input.split('');

  // Join the characters together, with the optional whitespace inbetween.
  let joinedString = splittedString.join(glueRegex)

  // Add the actual input as well, in case it is an exact match.
  joinedString += '|' + input;

  // Make a new regex made out of the joined string.
  // The 'i' indicates that the regex is case insensitive.
  return new RegExp(joinedString, 'i');
}



let userInput = 'icecream';
let keywords = "ice cream, ice cream cone, plastic container lid";

let input = makeRegEx('icecream');

// Check if any of the keywords match our search.
if (keywords.search(input) > -1) {
  console.log('We found the search in the given keywords on index', keywords.search(input));
} else {
  console.log('We did not find that search in the given keywords...');
}

Or this:

var input = new RegExp('icecream'.split('').join('(\\s)*').concat('|icecream'), 'i');
var keywords = "ice cream, ice cream cone, plastic container lid";

if (keywords.search(input) != -1) {

//do Something

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

1 Comment

No problemo! Would you mind setting this as the accepted answer?
1

you could do it like that:

let iceexpression=/ice\s*cream/g
let input="testinput icecream";
if(input.search(iceexpression)){
console.log("found");
}

1 Comment

Thanks @basicn00b, but how would I be able to apply this to any situation for example if the user inputs "cashcow" whereas the key words has "cash cow" or "takeout" but the keyword is "take out". Also removing whitespace would mitigate cases where whitespace would actually result into a match, such as "plastic container lid" would turn into "plasticcontainerlid"
1

Do you need the search to be a regex? If it would be sufficient to simply search for a keyword, you could use indexOf and first remove the whitespaces

var input = 'icecream';
var keywords = "ice cream, ice cream cone, plastic container lid";

if (keywords.replace(/\s/g, '').toLowerCase().indexOf(input) != -1) { alert('success!'); }

Edit: Modification to enable different searches

var searches = ['icecream', 'cashcow', 'takeout', 'otherthing']; // array with your searches
var keywords = "ice cream, ice cream cone, plastic container lid"; // input by the user

var tmpKeywords = keywords.replace(/\s/g, '').toLowerCase(); // remove spaces and convert to all lower case
var length = searches.length;
for (var i=0; i<length; i++) { // loop through all the seach words
    if (tmpKeywords.indexOf(searches[i]) != -1) {
        console.log(searches[i] + ' exists in the input!');
    }
}

2 Comments

Thanks @wawa, but how would I be able to apply this to any situation for example if the user inputs "cashcow" whereas the key words has "cash cow" or "takeout" but the keyword is "take out". Also removing whitespace would mitigate cases where whitespace would actually result into a match, such as "plastic container lid" would turn into "plasticcontainerlid"
@iceicebabeh I've added a version, where you can supply an array of search keywords.
0

In below solution I not use regexp but I generate new keyword list based on combinations of two words (between comma) of previous list.

var input1 = "ice cream"
var input2 = "icecream"
var input3 = "plastic lid"

var keywords = "ice cream, ice cream cone, plastic container lid";

let merge = a => {
    let result=[a.join(' ')];
    a.forEach((x,i)=>{  
        for(let j=i+1; j<a.length; j++) result.push(x+a[j])  
        for(let j=i+1; j<a.length; j++) result.push(x+' '+a[j])  
    });
    return result;
} 

let moreKeywords = keywords.split(', ').map( k=> merge(k.split(' ')) ).flat();

if(moreKeywords.includes(input1)) console.log('contains',input1);
if(moreKeywords.includes(input2)) console.log('contains',input2);
if(moreKeywords.includes(input3)) console.log('contains',input3);

console.log('moreKeywords:', moreKeywords);

Comments

0

You could use a wildcard such as /ice *cream/g

You can try out your regex here and read up on different inputs here

Here is an updated example to work with any input

var keywords = "ice cream, ice cream cone, ice cream c, plastic container lid";


  function search()
  {
    var textToFind = document.getElementById("searchInput").value;
    var input = new RegExp(textToFind.toString() + "*", "i");
    var words = keywords.split(",");
    words.forEach(function(word) {
      if(word.match(input))
      {
       console.log(word);
      }
    });
  }
<input id="searchInput"\>
<button id="search" onclick="search()">search</button>

4 Comments

Thanks @Josh Adams, but how would I be able to apply this to any situation for example if the user inputs "cashcow" whereas the key words has "cash cow" or "takeout" but the keyword is "take out"
@iceicebabeh you would need to take the user "search"/input to create your regular expression. I can add a simple search example if you'd like
that would great and much appreciated
@iceicebabeh check out my update and see if it helps

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.