6
\$\begingroup\$

I have a string like the one below from which I am extracting the tariff name.

const url = "https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars"

So from the above string, I want text tariffSelectionG_E5449168 and I am using the code below at the moment, which is working fine.

const supplyUrl = "https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars" if(supplyUrl.includes('?')) { const url = supplyUrl.split('?') if(url.length > 0) { const tariff = url[0].split('supplier/') return tariff[1] } } 

Is there any better way to do the above extracting?

\$\endgroup\$
2
  • 3
    \$\begingroup\$You could leverage named capturegroups like re = /https.*?supplier\/(?<param>.*)\?/g; re.exec(supplyUrl).groups["param"] to retrieve the same result more compact.\$\endgroup\$CommentedNov 24, 2021 at 10:42
  • 1
    \$\begingroup\$If your environment supports it, you could use the URL constructor.\$\endgroup\$
    – morbusg
    CommentedNov 24, 2021 at 14:13

5 Answers 5

4
\$\begingroup\$

While it may be unlikely to occur, the URL could contain a hostname with a top-level domain supplier. Currently .supplies is registered to Donuts Inc and someday URLs could have a TLD with supplier, which would lead the current code to not correctly find the target text.

const supplyUrl = "https://my.supplier/supplier/tariffSelectionG_E5449168?t=randomChars" if(supplyUrl.includes('?')) { const url = supplyUrl.split('?') if(url.length > 0) { const tariff = url[0].split('supplier/') console.log('tariff:', tariff[1]) } }

A more robust solution would use the URL API with the pathname property. For example, if it was known that the last part of the pathname was the tariff string then the array method .pop() could be used:

const supplyUrl = "https://my.supplier/supplier/tariffSelectionG_E5449168?t=randomChars" console.log('tariff: ', new URL(supplyUrl).pathname.split(/\//).pop());

Otherwise if there is a need to find strings anywhere in the path that start with tariff then a pattern match could be used for that - for example:

const supplyUrl = "https://my.supplier/supplier/tariffSelectionG_E5449168?t=randomChars" function findTariff(url) { const pathParts = new URL(url).pathname.split(/\//); for (const part of pathParts) { if (part.match(/^tariff/)) { return part; } } return -1; // or something to signify not found } console.log('tariff: ', findTariff(supplyUrl));

Or one could take a functional approach, which can be more concise:

const supplyUrl = "https://my.supplier/supplier/tariffSelectionG_E5449168?t=randomChars" function findTariff(url) { const pathParts = new URL(url).pathname.split(/\//); return pathParts.find(part => part.match(/^tariff/)); } console.log('tariff: ', findTariff(supplyUrl));

\$\endgroup\$
    5
    \$\begingroup\$

    Super short review;

    • The code should handle the presence or the absence ? in a transparent way
    • The code should probably check for /supplier/ instead of ?

    That leaves me with

    function extractTariffName(url){ const resource = '/supplier/'; if(url.contains(resource)){ return url.split('?').shift().split(resource).pop(); } //return undefined } console.log(extractTariffName('https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars')); console.log(extractTariffName('https://any-api/supplier/tariffSelectionG_E5449168')); console.log(extractTariffName('https://any-api/supliar/tariffSelectionG_E5449168')); 
    \$\endgroup\$
      3
      \$\begingroup\$

      I think for any url related task you have two good tools as

      1. The URL API
      2. The URLPattern API

      With the URL constructor you may do like;

      var url = new URL("https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars"), tariffCode = url.pathname.slice(url.pathname.lastIndexOf("/")+1); 

      URLPattern API, on the other hand is more powerful and convenient for this job despite being a little comprehensive. Keep in mind that it's a recent API and available in Chrome 95+. Server side, it is available in Deno (which i like very much) and possibly in recent Node versions too.

      In this particular case we can generate an URL Pattern which takes the path up until a variable that we declare. This variable represents the url portion of our interest. Lets name it tariff. Accordingly

      var pat = new URLPattern({pathname: "/supplier/:tariff"}); 

      Thats it.

      Once you receive an url first you can test it's validity against the pattern like;

      pat.test("https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars"); // <- true 

      If true then you can extract your tariff code like

      var tariffCode = pat.exec("https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars") .pathname.groups.tariff; // <- "tariffSelectionG_E5449168" 
      \$\endgroup\$
      1
      • \$\begingroup\$Reminder: the URLPattern API is still experimental in 2023 and not implemented in Mozilla Firefox and Safari.\$\endgroup\$
        – gouessej
        CommentedFeb 7, 2024 at 14:30
      1
      \$\begingroup\$

      If you can, use the URL constructor. It is a bit clearer semantically:

      const supplyUrl = new URL("https://any-api/supplier/tariffSelectionG_E5449168?t=randomChars"); const parts = supplyUrl.pathname.split("/"); // the 0th item is empty since the pathname starts with a slash const tariff = parts[2]; 
      \$\endgroup\$
        0
        \$\begingroup\$

        Get text before '?' with split('?').at(), then reverse it and get text before '/' and reverse it back ;) supplyUrl.split('?').at().split('').reverse().join('').split('/').at().split('').reverse().join('')

        \$\endgroup\$

          Start asking to get answers

          Find the answer to your question by asking.

          Ask question

          Explore related questions

          See similar questions with these tags.