How to include Parentheses () in the string when using Template literals?
Currently its output:
Test Yes Test
I expect to output like this with the parentheses:
Test (Yes) Test
Code:
let type = "Yes";
let string = `Test ${type? (type) : ''} Test`;
console.log(string);
You can use template in the template
const type = 'yes';
const string = `Test ${type? `(${type})` : ``} Test`;
console.log(string)
You need to specify that the parenthesis are part of the string and not just order of operations.
let string = `Test ${type? "(" + type + ")" : ''} Test`;
You can wrap the entire placeholder:
let type = 'yes';
let string = `Test (${type? type : ''}) Test`;
console.log(string)
Or if you need to not include it if type is falsy then you can concat them with + or use a nested placeholder:
let type = 'Yes';
let string = `Test ${type ? `(${type})` : ''} Test`;
console.log(string)
And just for fun you can write a Tagged template to make it more reusable:
function myTag(strings, ...values) {
let result = '';
strings.forEach((string, i) => {
// strings will always be +1 length over values as per the spec
const value = values[i] ? `(${values[i]})` : ''
result += string + value;
});
return result;
}
const test1 = "Yes";
const result1 = myTag`Test ${test1} Test`;
console.log(result1);
const test2 = null;
const result2 = myTag`Test ${test2} Test`;
console.log(result2);
Related
I need to replace all characters of an incoming string with the corresponding ones from an object, how can I do this using an array?
function handleCyrillic(str) {
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
let res = "";
const arr = Object.keys(obj);
arr.forEach((item) => {
const regex = new RegExp(item, "gi");
res += str.replace(regex, function (s) {
return s
.split("")
.map((n) => (n = obj[n]))
.join("");
});
});
return res;
}
console.log(handleCyrillic("цй йй!!"));
I get in the console ц\'e9 \'e9\'e9!!\'f6й йй!!
I expected \'f6\'e9 \'e9\'e9!!
The problem is that res variable is being overwritten each time a character is replaced instead of appending the replacement to the result. This is updated and a bit refactored version:
function handleCyrillic(str) {
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
let res = str;
Object.keys(obj).forEach((key) => {
const regex = new RegExp(key, "gi");
res = res.replace(regex, obj[key]);
});
return res;
}
You just need to join your obj keys and surround with square brackets for the or condition and in the replace method callback replaces the match string with the corresponding replacement in the obj.
function handleCyrillic(str) {
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
const arr = Object.keys(obj);
const regex = new RegExp(`[${arr.join()}]`, "gi");
return str.replace(regex, function(s) {
return obj[s]
});
}
console.log(handleCyrillic("цй йй!!"));
In your code you are replacing on the str which is parameter which never going to be change and you are concate that into the res which is function return variable that's why you are not getting desired output
function handleCyrillic(str) {
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
let res = str;
const arr = Object.keys(obj);
arr.forEach((item) => {
const regex = new RegExp(item, "gi");
res = res.replace(regex,obj[item]);
});
return res;
}
console.log(handleCyrillic("цй йй!!"));
Try this. At first split the string. If a character exists as a key in the obj, map() returns the obj value, if not it returns the current character. In the end join the string.
function handleCyrillic(str) {
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
return str.split('').map(char => obj[char] || char).join('');
}
console.log(handleCyrillic("цй йй!!"));
There is no need for a regular expression here. You can use Array.from with its callback:
const obj = {
й: "\\'e9",
ц: "\\'f6",
};
const handleCyrillic = str => Array.from(str, ch => obj[ch] ?? ch).join("");
console.log(handleCyrillic("цй йй!!"));
The ?? operator deals with cases where there is no mapping for a character. This still allows a mapping to the empty string to be included in obj, which means you want to remove a character.
There's no need for this conversion table in the first place. Basic Unicode Cyrillic is continuous in range 410...44f and Win-1251 is c0..ff, so you can just do some codepoint arithmetics to convert between both:
function handleCyrillic(str) {
let res = ''
for (let chr of str) {
let cp = chr.codePointAt(0)
if (0x410 <= cp && cp <= 0x44f)
res += "\\'" + (cp - 0x410 + 0xc0).toString(16)
else
res += chr
}
return res;
}
console.log(handleCyrillic("цй йй!!"));
I have a string that has parameters separated with ampersands , for example :
orderid=55e3a83e&DealId=545435&Amount=590 ....
How can I convert that into a Key/Value Map ?
My current code is as follows :
const text = "orderid=55e3a83e&DealId=545435&Amount=590 ...."
let _key = "";
let _value = "";
var myregexp = /([^&=]+)=(.*?)(?=&[^&=]+=|$)/g;
var match = myregexp.exec(text);
while (match != null && key !== "url") {
_key = match[1];
_value = match[2];
dict.push({
key: _key,
value: _value
});
match = myregexp.exec(subject);
}
But it's too long , any idea for something better or shorter ?
You can split first by & and then split each element by =, and build a key/value pair
let mapper = (str) => str.split('&').filter(Boolean).map(v => {
let [key, value] = v.split('=')
return { key, value }
})
console.log(mapper('orderid=55e3a83e&DealId=545435&Amount=590 '))
In case desired output in the form of a single object
let mapper = (str) => {
let splitted = str.split('&').map(v => v && v.split('=')).filter(Boolean)
return Object.fromEntries(splitted)
}
console.log(mapper('orderid=55e3a83e&DealId=545435&Amount=590 '))
I've always used some code very similar to your current solution:
function getUrlParams(input) {
var params = {};
input.replace(/[?&]+([^=&]+)=([^&]*)/g, (m, key, value) => {
params[key] = value;
});
return params;
}
Of course, this doesn't ignore the URL parameter, and it returns a plain JS object... but you get the idea.
The string looks like a URL query, you can use URLSearchParams to parse it, here is an example:
const usp = new URLSearchParams('orderid=55e3a83e&DealId=545435&Amount=590');
const dictionary = [];
for (const [key, value] of usp.entries()) {
dictionary.push({ key, value})
}
console.log(dictionary);
This is the result of the console.log below:
console.log('subscribe:', event.url);
"https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ?success=true"
Where I want to strip src_1E2lmZHazFCzVZTmhYOsoZbg and src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ
How to achieve this?
Convert the string to a url, read the pathname and than split on / and take the last two parts.
var str = "https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ?success=true"
const parts = new URL(str).pathname.split('/').slice(-2)
console.log(parts)
If the query parameter ?success=true is optional (as in most cases is) you could
function getSrcAndSecret (url) {
const pts = /\/(src_[^/?]+)\/(src_client_secret_[^/?]+)/.exec(url);
return {
src: pts && pts[1] || "",
secret: pts && pts[2] || ""
}
}
// Demo:
const test1 = getSrcAndSecret("https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ?success=true");
const test2 = getSrcAndSecret("https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ");
const test3 = getSrcAndSecret("https://hooks.stripe.com/adapter/ideal/redirect/complete");
console.log(test1, test2, test3)
const url = "https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ?success=true";
const res = url.split(/\?|\//g).filter(el => el.startsWith("src"));
console.log(res)
const [a, b] = event.url.split("?")[0].split("/").slice(-2);
I need to convert this string into object
var str = "res=[xyz=name,abc=address]";
I need below output :
var obj = {xyz: "name",abc:"address"}
I tried to convert this by using json.parse and split but I can't get the result .can anyone help to do this ?
This code works with the string given. It is also very readable for noobs
var str = "res=[xyz=name,abc=address]";
str = str.split("res=")[1]
.replace("[",'{"')
.replace("]",'"}')
.replace(/=/g,'":"')
.replace(/,/g,'","');
res = JSON.parse(str);
console.log(str,"\n",res);
One more Implementation:
//str format "res=[xyz=name,abc=address]"
function stringToObject(str){
const extractedStr = str.substring(str.indexOf("[")+1,str.indexOf("]")-1);
return extractedStr.split(",").reduce((acc,keyVal)=>{
acc[keyVal.split("=")[0]] = keyVal.split("=")[1];
return acc;
},{});
}
console.log(stringToObject("res=[xyz=name,abc=address]"));
Here's a way to do it:
// format your input like this, comma separated, and key=val
const str = "xyz=name,abc=address"
const obj = str.split(',').reduce((acc, keyVal) => {
const [key, val] = keyVal.split('=')
acc[key] = val
return acc
}, {})
console.log(obj)
// { xyz: "name", abc: "address" }
Another implementation
let str = "res=[xyz=name,abc=address]";
let convertStrToObject = (str) => {
return str
.substring(5, str.length - 1)
.split(",")
.reduce((acc, item) => {
acc[item.split("=")[0]] = item.split("=")[1];
return acc;
}, {});
};
console.log(convertStrToObject(str));
let string = 'My name is [~FIRSTNAME] [~LASTNAME]';
let nameArray = ['Peter', 'Parker'];
let patternToBeReplaced = ['[~FIRSTNAME]', '[~LASTNAME]']
I want to replace the string with the elements of namearray so that the string becomes 'My name is Peter Parker'
Below is my approach to this problem -
patternToBeReplaced.forEach(function (match, index) {
var output = string.replace(match, nameArray[index]);
});
But this is not working as expected.
You could use Array#reduce and use the string for the next replacement.
let string = 'My name is [~FIRSTNAME] [~LASTNAME]';
let nameArray = ['Peter', 'Parker'];
let patternToBeReplaced = ['[~FIRSTNAME]', '[~LASTNAME]']
string = patternToBeReplaced.reduce((s, m, i) => s.replace(m, nameArray[i]), string);
console.log(string);
You're creating a string templating system. Since you're using ECAMScript 6 syntax already, you could use the new built-in template literals.
let [FIRSTNAME, LASTNAME] = ['Peter', 'Parker'];
let string = `My name is ${FIRSTNAME} ${LASTNAME}`;
console.log(string);
This will also work more cleanly when there are multiple insertions of a given label within the string.
let [FIRSTNAME, LASTNAME] = ['Peter', 'Parker'];
let string = `My name is ${LASTNAME}... ${FIRSTNAME} ${LASTNAME}`;
console.log(string);
patternToBeReplaced.forEach(function (match, index) {
string = string.replace(match, nameArray[index]);
});
Something like that.
let str = 'My name is [~FIRSTNAME] [~LASTNAME]';
let nameArray = ['Peter', 'Parker'];
let patternToBeReplaced = ['[~FIRSTNAME]', '[~LASTNAME]']
const result = patternToBeReplaced.reduce((str, placeholder, i) => {
return str.replace(placeholder, nameArray[i]);
}, str);
console.log(result);
output is a local variable, it's useless to just declaring it.
replace(String, String) would only replace the first matched pattern.
Here's my solution:
let replaceWithArrayElements = (patterns, replacements, targetString) => {
patterns.forEach((pattern, i) => targetString = targetString.replace(new RegExp(pattern, 'g')));
return targetString;
}
First solution, keeping your base code :
let string = 'My name is [~FIRSTNAME] [~LASTNAME]';
let nameArray = ['Peter', 'Parker'];
let patternToBeReplaced = ['[~FIRSTNAME]', '[~LASTNAME]'];
patternToBeReplaced
.forEach((match, i)=>{
string = string
.replace(match, nameArray[i]);
});
Using Map:
let string = 'My name is [~FIRSTNAME] [~LASTNAME]';
let replaceMap = new Map();
replaceMap.set('[~FIRSTNAME]', 'Peter');
replaceMap.set('[~LASTNAME]', 'Parker');
replaceMap.forEach((key, value)=>{
string = string.replace(key, value);
});
Using ES6 "template" strings:
/*
*Have some ways of getting the first name in "firstName"
*Have some ways of getting the last name in "lastName"
*/
let string = `My name is ${firstName} ${lastName}`;
string.match(/\[~\w+\]/g).forEach((item,index)=>{
string = string.replace(item, nameArray [index])
})
You can use the above code for you needs