1

I have a sentence which looks like below

term = "How much new sales in new"

Say I get a some suggestions like New York, New Delhi, Papua New Guinea and I select New York.

choice = "New York"

Now I need to ensure that any latest substring that matches the selection is replaced with the selection.

So ideally my string should now become

term = "How much new sales in New York"

So this is what I do

terms = term.split(/\s+/g)
choice_terms = choice.split(/\s+/g)
terms.pop() //remove the last substring since this is what the user typed last
check_terms = terms

// get the latest instance of first term of the selection
if(user_choice_terms.length > 1) {
    if(check_terms.lastIndexOf(user_choice_first_term) !== -1) {
            last_index = check_terms.lastIndexOf(user_choice_first_term)
            check_terms.splice(-last_index)            //remove anything after the matched index
            check_terms.push(...user_choice_terms)     //add the selected term
            return check_terms
    }
 }

But this doesn't seem like a reliable solution and I would rather use a regex. The user may also type like this

term = "How much new sales in new     yo"

Here I am guaranteed to get a suggestion New York against yo and should be replaced with New York

Is there any regex solution to ensure the latest substring match is completely replaced with the selection?

Note: I am using jquery ui autocomplete

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Souvik Ray
  • 2,899
  • 5
  • 38
  • 70
  • 1
    Check out the meaning of `$` in regex. (https://stackoverflow.com/questions/8327705/what-are-and-in-regular-expressions) – Daniel F Jun 18 '20 at 06:47
  • @DanielF yes sure but I do not understand how will I handle `new yo` even if I detect it. – Souvik Ray Jun 18 '20 at 07:12
  • `((\w+)?\ *\w+\ *)$` where group 1 (`\1`) will be your query term, where you replace all consecutive spaces with one single space before searching in your database. – Daniel F Jun 18 '20 at 07:29

1 Answers1

1

You may create a pattern that will match all possible prefixes of the choice with all spaces replaced with \s+ pattern to match 1 or more whitespaces and adding $ at the end of the pattern to only match at the end of the string:

/N(?:e(?:w(?:\s+(?:Y(?:o(?:r(?:k)?)?)?)?)?)?)?$/i

It will match N, Ne, New, etc. with any amount of whitespace between New and York, and only at the end of the string due to $.

See the regex demo

See JavaScript demo:

const make_prefix = (string) => {
    let s = string.charAt(0);
    for (let i=1; i<string.length; i++) {
        s += "(?:" + string.charAt(i);
    }
    for (let i=1; i<string.length; i++) {
        s += ")?";
    }
    return s;
}

const term = "How much new sales in new      yo";
const choice = "New York";
const regex = new RegExp(make_prefix(choice).replace(/\s+/g, '\\s+') + '$', 'i');
console.log(term.replace(regex, choice))
// => How much new sales in New York
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • this solution is great. But can you put a check whether the replacement is successful or not? In other words whether prefix matched or not. I plan to trigger another piece of code incase the prefix didn't match. – Souvik Ray Jun 18 '20 at 09:11
  • @SouvikRay You may use `if (regex.test(term)) { term = term.replace(regex, choice); } else { /* FALLBACK IF NO MATCH */ }` – Wiktor Stribiżew Jun 18 '20 at 09:24
  • hello! There is a problem with the regex. If my term is `name` and choice is `endice name` ,then the final term is `namendice name` instead of `name endice name`. Can you check? – Souvik Ray Jun 18 '20 at 17:20
  • @SouvikRay It appears to me that there should be no match in this case, you need to match at word boundary, `const regex = new RegExp("\\b" + make_prefix(choice).replace(/\s+/g, '\\s+') + '$', 'i');` – Wiktor Stribiżew Jun 18 '20 at 17:29
  • yes this seems to have fixed the problem. Needed to add a word boundry. Thanks again! – Souvik Ray Jun 18 '20 at 17:44
  • Hi Wiktor. I need your help once again. Do you think the regex can be improved to consider a situation where the the ending characters may not be related to the suggestions? For example `const term = "How much new sales in new yo abcd";` `const choice = "New York";` Here you can see the `term` ends with some characters `abcd` and the match fails. Do you think the regex can be improved to look for latest substring irrespective how the `term` ends? – Souvik Ray Jun 24 '20 at 09:55
  • @SouvikRay Probably something like `new RegExp("\\b" + make_prefix(choice).replace(/\s+/g, '\\s+') + '(?!.*\\b' + make_prefix(choice).replace(/\s+/g, '\\s+') + ')' , 'i');` – Wiktor Stribiżew Jun 24 '20 at 10:04
  • 1
    hi Wiktor I have tried this and this works for me. Thanks again! – Souvik Ray Jun 24 '20 at 12:09