3

I have new RegExp(`\\b${escapedQuery}`, "i") regex to search words boundary , where escapedQuery is escaped value after lodash's escapeRegExp function.

const BRANDS = [
  "Alexander McQueen",
  "Alexandre De Paris",
  "alexander.t",
  "A.W.A.K.E. MODE",
  "alexanderwang.t",
  "MARC JACOBS (THE)"
];

function filter(query) {
  return BRANDS.filter((brand) => {
    const escapedQuery = escapeRegExp(query);
    const re = new RegExp(`\\b${escapedQuery}`, "i");
    return re.test(brand);
  });
}

But if I pass a dot or bracket symbol, then I don't get the value I expected.

console.log(filter("al")); // OK [  "Alexander McQueen",  "Alexandre De Paris",  "alexander.t",  "alexanderwang.t"]
console.log(filter("M")); // OK [  "Alexander McQueen", "A.W.A.K.E. MODE", "MARC JACOBS (THE)"]
console.log(filter(".")); // Expected [""] - Actual ["alexander.t", "A.W.A.K.E. MODE", "alexanderwang.t"]
console.log(filter("(")); // OK [""] 
console.log(filter(")")); // Expected [""] - Actual ["MARC JACOBS (THE)"]

Here is Sandbox to better understanding expected and actual results

What needs to be fixed in the expression so that it returns the expected value?

J. Doe
  • 502
  • 1
  • 7
  • 16
  • Try ``const re = new RegExp(`(?:\\s|^)${escapedQuery.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}`, "i");`` – Wiktor Stribiżew Sep 16 '22 at 12:36
  • Thank's, I tried this, but in case when we pass `alexanderwang.` (with dot) the function returns [] and I want it to return `['alexander.t']` – J. Doe Sep 16 '22 at 13:14
  • How about [requiring](https://www.regular-expressions.info/lookaround.html) a [word character `\w`](https://stackoverflow.com/a/2998550/5527985) after the boundary: `\\b(?=\\w)${escapedQuery}` – bobble bubble Sep 16 '22 at 13:26

1 Answers1

0

You can require the first char to be always a word char:

function filter(query) {
    return BRANDS.filter((brand) => {
        const re = new RegExp(`(?=\\w)${query.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}`, "i");
        return re.test(brand);
   });
}

See the demo below:

const BRANDS = [
  "Alexander McQueen",
  "Alexandre De Paris",
  "alexander.t",
  "A.W.A.K.E. MODE",
  "alexanderwang.t",
  "MARC JACOBS (THE)"
];

function filter(query) {
  return BRANDS.filter((brand) => {
    const re = new RegExp(`(?=\\w)${query.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}`, "i");
    return re.test(brand);
  });
}

console.log(filter("al")); // OK [  "Alexander McQueen",  "Alexandre De Paris",  "alexander.t",  "alexanderwang.t"]
console.log(filter("M")); // OK [  "Alexander McQueen", "A.W.A.K.E. MODE", "MARC JACOBS (THE)"]
console.log(filter(".")); // Expected [""] - Actual ["alexander.t", "A.W.A.K.E. MODE", "alexanderwang.t"]
console.log(filter("(")); // OK [""] 
console.log(filter(")")); // Expected [""] - Actual ["MARC JACOBS (THE)"]
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • can we modify the regexp so it matched only words from start: BRANDS.push('Arctic Explorer'); filter('ar') //Expected ['Arctic Explorer'] - Actual ['Alexandre De Paris', 'MARC JACOBS (THE)']? – J. Doe Oct 10 '22 at 11:34
  • @J.Doe sure, just replace the `(?=\\w)` at the start of the regex with `^`. – Wiktor Stribiżew Oct 10 '22 at 12:24