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?
5 Answers 5
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));
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'));
I think for any url related task you have two good tools as
- The URL API
- 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"
-
\$\begingroup\$ Reminder: the
URLPattern
API is still experimental in 2023 and not implemented in Mozilla Firefox and Safari. \$\endgroup\$gouessej– gouessej2024年02月07日 14:30:16 +00:00Commented Feb 7, 2024 at 14:30
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];
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('')
re = /https.*?supplier\/(?<param>.*)\?/g; re.exec(supplyUrl).groups["param"]
to retrieve the same result more compact. \$\endgroup\$