1

The URL query after a decodeURIComponent and a split() looks like this ["pcs_availability:Online", "price:[1500 TO 1999.99]"] the results I am looking for is returning an array with the proper integer like [1999.99]. But there can be more than 1 price range in URL query string for example ["pcs_availability:Online", "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"]. Which should return [499.99, 999.99, 1999.99]. I forgot to mention that the price positioning in the array could be different depending on the other URL queries. So that it's not always going to be guaranteed to be in the same spot.

This was the approach taken.

const pattern = /^price:{1,2}\[.*? TO (.*)]$/;
const price = query
  .map(q => {
    const match = pattern.exec(q);
    return match;
  });

Which returns this. I tried modifying the regex but unfortunately I haven't been able to get the results that I am looking for.

["price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]", "1999.99", index: 0, input: "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]", groups: undefined]
Jack Bashford
  • 38,499
  • 10
  • 36
  • 67
steven5210
  • 93
  • 7
  • 2
    It's been said that the synonym for Regex is Regrets :) Are you married to using Regex for this? A simple function would be more readable, which is normally a high priority among seasoned developers. – Brian Patterson May 06 '20 at 22:27
  • 2
    What you have requested are not *integers*, but rather *floats* – Yevgen Gorbunkov May 06 '20 at 22:32
  • 1
    @BrianPatterson No not at all, my first solution was something like this `const price = query.find((item) => item.match("price")).split(/::|:/)[1].split(" ")[2].replace("]", "");`. But wasn't quite able to get the results I was looking for. – steven5210 May 06 '20 at 22:40

2 Answers2

2

Would that work for you?

const arr = ["pcs_availability:Online", "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"]

      result = arr
        .find(e => e.includes('price'))
        .match(/(?<=TO )\d+\.\d+/g)
      
console.log(result)
.as-console-wrapper{min-height:100%;}
Yevgen Gorbunkov
  • 12,646
  • 3
  • 13
  • 31
  • Wow that's really good! The only issue is that it's currently an array like `["pcs_availability:Online", "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"]`. Otherwise your answer is perfect – steven5210 May 06 '20 at 22:33
  • Nevermind I just did .toString().match but is there a more efficient way without having to do a `.toString()`? – steven5210 May 06 '20 at 22:34
  • It is a valid array, and just `arr[1]` would get the string with prices in it. Though it would be unreliable if the price index isn't guaranteed. – Emile Bergeron May 06 '20 at 22:41
  • @YevgenGorbunkov it is basically one array with strings inside of it. Each string is separated by a comma. Sorry if it looks a bit confusing. `["pcs_availability:Online", "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"]` This is one string `"pcs_availability:Online"` and this is the second string in the array `"price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"` – steven5210 May 06 '20 at 22:44
  • 1
    @steven5210 : my bad (got to go to sleep ;), check out the latest edit – Yevgen Gorbunkov May 06 '20 at 22:45
  • @YevgenGorbunkov No problem :) Thanks for the help! Have a good sleep! – steven5210 May 06 '20 at 22:50
  • The [comma operator](https://stackoverflow.com/q/9579546/1218980) trick is clever, but should never be used in code intended for programmers. Let the minifier compress the code. – Emile Bergeron May 06 '20 at 23:00
  • @EmileBergeron what would you suggest instead? It looks like eslint does not take kindly to the comma operator either so this won't pass the code linting. – steven5210 May 06 '20 at 23:02
  • 1
    `(r,str) => { r.push(...str.match(/(?<=TO )\d+\.\d+/g) || []); return r; }` on their own lines. – Emile Bergeron May 06 '20 at 23:06
  • @EmileBergeron : *'..comma operator ....should never be used'* Comma operator is a standard well documented feature. Can't see the problem *deciphering* 2 expressions, separated by comma. One might find `reduce()` method hard to read. Does it mean it should also be sacrificed in favor of `for(..`-loop not to hurt someone's religious beliefs? What else, keep telling the Earth is flat? – Yevgen Gorbunkov May 07 '20 at 08:03
2

Firstly, save the string you want into a variable - then split off the first part ("price"), and then just map the rest with a numbers and dot matching regex, converting into a number at the end:

const data = ["pcs_availability:Online", "price:[250 TO 499.99]:[500 TO 999.99]:[1500 TO 1999.99]"];

let str = data.find(e => e.includes("price"));

let [,...allPrices] = str.split(":");

let prices = allPrices.map(s => s.split("TO")[1].match(/[0-9\.]+/)[0]);

prices = prices.map(n => +n);

console.log(prices);
.as-console-wrapper { max-height: 100%; top: auto; }
Jack Bashford
  • 38,499
  • 10
  • 36
  • 67
  • 1
    Sorry, I forgot to mention that the price might not always be in the same position/index in the array depending on other data. I will update my post – steven5210 May 06 '20 at 23:03
  • Fixed @steven5210 – Jack Bashford May 06 '20 at 23:10
  • @steven5210: Just for your notice, there is certainly [the way](https://stackoverflow.com/a/61646519/11299053) to achieve the result with less lines and [CPU cycles](https://jsbench.me/pvka1br0en/1). Though, it might seem to [some people](https://stackoverflow.com/users/1218980/emile-bergeron) the more lines, the greater is the virtue of readability, also it may give a feeling of great difficulties being overcame ;) – Yevgen Gorbunkov May 10 '20 at 17:32