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\$ Nov 24 '21 at 10:42
  • 1
    \$\begingroup\$ If your environment supports it, you could use the URL constructor. \$\endgroup\$
    – morbusg
    Nov 24 '21 at 14:13
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\$

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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.