Replace {something} inside a string with variables - javascript

I have a string like:
const string = "Use this {amount} to bring a little joy into someone else's life."
const amount = Math.floor(Math.random() * 100) + 1; // Assume it gave me 34 this time.
const replacedString = // Somehow replace "{amount}" inside string with actual amount variable.
I want his for not only "{amount}" this could be anything like "{abc}", "{foo}", "{bar}" etc...
Use case for this is something like:
I have array of random string containing strings which have replaceable variables inside them like:
const array = [
"string 1 have {amount}",
"string 2 have {amount} as well as {user}",
"string 3 have {amount} as well as {user} and their {bank.balance}"
]
Now a function returns random elemnt from this array in a variable:
const response = getRandomElem(array) // This is a custom function
Now I want to use a replace method which I described above so that I can replace the variables.
I know intermediate javascript, so please include examples so that i can understand.

Take a look at this one-liner!
const replace = (string, object) => string.replaceAll(/\{([^}]+)\}/gi, (_, a) => a.split('.').reduce((b, c) => b?.[c], object));
You'll need to define your replacements as key-value pairs like this:
const repl = {
amount: 100,
user: "Michael Jackson",
bank: {
balance: 100
}
}
A simple example here:
const array = [
"string 1 have {amount}",
"string 2 have {amount} as well as {user}",
"string 3 have {amount} as well as {user} and their {bank.balance}"
]
const repl = {
amount: 100,
user: "Michael Jackson",
bank: {
balance: 100
}
}
const replace = (string, object) => string.replaceAll(/\{([^}]+)\}/gi, (_, a) => a.split('.').reduce((b, c) => b?.[c], object));
console.log(array.map(e => replace(e, repl)));

The simplest solution is to create a "template context" object that contains all the replacement values. Then, iterate over each template and use the context to generate the resulting strings.
Then, iterate over the template and use the context to generate the resulting string:
Hello{name}, welcome to {project}
You could create a context object like this:
const context = { name: 'John', project: 'MyProject' };
let output = ''
Object.keys(context).forEach(key => { const regexp = new RegExp(`{${key}}`, 'g')
output = template.replace(regexp, context[key]); })
console.log(output); // Hello John, welcome to MyProject

You can simply achieve this by replace the { into a template literal syntax and then interpolate the string into a template string.
Live Demo :
// Input array
const arr = [
"string 1 have {amount}",
"string 2 have {amount} as well as {user}",
"string 3 have {amount} as well as {user} and their {bank.balance}"
];
// Variables holding the values
const amount = Math.floor(Math.random() * 100) + 1;
const user = 'Alpha';
const bank = {
balance: 500
};
// Iterating the array to map the values against each '{...}'
const res = arr.map(str => {
// replacing the '{' with '${' to support the template literal format.
str = str.replace(/{/g, '$\{')
// Interpolate the string into a template string.
return new Function(`return \`${new String(str)}\`;`)();
});
// Final output
console.log(res);

You can use replace() function.
var name = 'John'
var age = 25;
var message = 'Hello, {name}! You have {age} years of age.'
message = message.replace('{name}', name).replace('{age}', age);

Related

Javascript Check Array with Object Keys using includes() but do not check the whole word

I have the following code. A body object and a sensitive word array.
If the body key contains any word from sensitive words, it should returns true.
const body = {
name: "",
email: "",
otpp: ""
}
const sensitiveWords = ["password", "pin", "otp"]
const isSensitive = sensitiveWords.some(el => Object.keys(body).map(name => name.toLowerCase()).includes(el)) || false
console.log(isSensitive);
// returns: false
// expected result: true
But as you can see, the word otp is in the sensitive words, but its not matching otpp. I guess its because its looking for full string match.
I need the above function to return true since the key contains otp in otpp.
Thank you.
You're looking for
const containsSensitive = sensitiveWords.some(el =>
Object.keys(body).some(name =>
// ^^^^
name.toLowerCase().includes(el)
// ^^^^^^^^ string search
)
)
I provide an solution using double some() to do it
const body = {
name: "",
email: "",
otpp: ""
}
let sensitiveWords = ["password", "pin", "otp"]
const isSensitive = (body,words) => Object.keys(body).map(n => n.toLowerCase()).some(d1 => words.some(d2 => d1.includes(d2)))
console.log(isSensitive(body,sensitiveWords)) // true
sensitiveWords = ["password", "pin", "otps"]
console.log(isSensitive(body,sensitiveWords)) // false
You can try using regex with case insensitive flag (i). This could be more performant than using two nested loops.
const body = {
name: '',
email: '',
password: ''
}
const sensitiveWords = ['password', 'pin', 'otp']
const sensitiveWordsRegex = new RegExp(sensitiveWords.join('|'), 'i')
const keys = Object.keys(body)
const hasSensitiveWord = keys.some(key => sensitiveWordsRegex.test(key))
console.log(hasSensitiveWord)
The answer of Bergi is the best one.
I just want to share what I worked on, I realized I made it so complicated.
Btw to explain why your code did not work is because:
You were searching the array for a word (the body object keys array Object.keys(body)) -- this will not work because you are basically comparing strings and not searching it for a substring
What you need to do is search the string for a substring
You'll have to iterate through the body keys and search each for a substring --> string.includes('string)
JsFiddle link
/*
** The answer of Bergi is the best one but just want to share what I worked on
** (https://stackoverflow.com/a/74150607/8414995)
** if you want it the hard way
*/
// Check if strings from an array matches a key (substring or whole word) of an object
const body = {
name: '', email: '', otpp: '',
}
// list of words to be searched in the body keys
const sensitiveWords = ['password', 'pin', 'otp']
// list down the keys first maybe to make the code clearer?
const bodyKeys = Object.keys(body)
// search through each word from sensitiveWords
const hasData = sensitiveWords.some(el => {
// iterate through each word from bodyKeys and check if the sensitive word matches a substring of the body key. Filter only the true values
const result = bodyKeys.map(bEl => {
// return true if it matches anything
if (bEl.includes(el)) {
return true
}
}).filter(el => el == true)
// the result will be in array form so let's just check if the length > 0
return !!result.length
})
console.log(hasData)
// Check if strings from an array matches a key (substring or whole word) of an object
I would try to json stringify the whole body and split to words and search on that

Best way to alter array of objects inside an object (using a string path)

This may be simpler than I think but is there an easy way to alter the array inside this object using a string:
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
This is what I am trying to achieve:
const name = "members[0].file_name" // STRING
temp = {...temp, [name]: 'changed'}
Output it's giving me:
Yes I can split that string to give me the keys and index then change the object the normal way but I was just wondering if there is an easier way about it.
You can take a look at lodash's set function that takes in a string path, and returns the nested object.
lodash does the parsing for you, so you don't have to
https://dustinpfister.github.io/2018/12/04/lodash_set/
You can use the eval() function which will return the object you want in accordance with a path
const temp = {
members: [{
file_name: 'abc',
file_link: 'www'
}]
}
const path = "members[0].file_name";
// Obtain last key (file_name)
const lastKey = path.split(".").at(-1);
// Obtain the path to the last key (members[0])
const previousPath = path.substr(0, path.length - (lastKey.length + 1));
// Get the object with the path (temp.members[0])
const e = eval(`temp.${previousPath}`)
// Modify object
e[lastKey] = "xyz";
console.log(temp)
You can achieve this the following way
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
const name = "file_name" // STRING
temp.members[0][name] = "changed";
console.log(temp);
Or like this:
var temp = {
members: [
{file_name: 'abc', file_link: 'www'}
]
}
const name = "file_name";
const arr = "members";
temp[arr][0][name] = "changed";
console.log(temp);

How to separate a string as according to a condition, using split?

good morning I have these text strings:
json_schema.account_overview.name
json_schema.no_owned.contact.contact
but now I'm trying to separate according to the string 'json_schema.no_owned', doing like this:
my_string.split ("json_schema.no_owned."). filter (x => x);
but doing a console.log of that result I get this
the first arrangement is fine, since to that same arrangement I can apply another split and I will have again separated by '.'
but the second fix has nothing to do with what I was saying should be after 'json_schema.no_owned.' (note the period at the end)
This way I am trying to do it:
let string ="json_schema.no_owned.contact.contact";
let arrayString = [
'json_schema.no_owned.contact.contact',
'json_schema.account_overview.name'
];
let schema = "";
for(let i in arrayString){
schema = arrayString[i].split("json_schema.no_owned.").filter(x => x);
console.log(schema);
}
I only want to have in an array the elements that are after 'json_schema.no_owned'
Thanks.
You can check if element has "json_schema.no_owned." part at all:
let string ="json_schema.no_owned.contact.contact";
let arrayString = [
'json_schema.no_owned.contact.contact',
'json_schema.account_overview.name'
];
let schema = "";
for(let i in arrayString){
if (arrayString[i].includes("json_schema.no_owned.")) {
schema = arrayString[i].split("json_schema.no_owned.").filter(x => x);
console.log(schema);
}
}
Maybe you can use a short way to do it.
let arrayString = [
'json_schema.no_owned.contact.contact',
'json_schema.account_overview.name'
];
const schemas = arrayString.filter(x => x.includes("json_schema.no_owned."))
.map(x => x.split("json_schema.no_owned.")[1]);

Is there a one-liner to convert '1234567' into ['1234', '567', '', '']?

I need to convert a string into an array with 4 elements, each element has maximum of 4 characters.
"1234567812345678" -> ["1234", "5678", "1234", "5678"]
"12345678123" -> ["1234", "5678", "123", ""]
"" -> ["", "", "", ""]
The reason I want it to be a one-liner is that I need to put it into vue template string so it needs to be an expression other than a series of statements.
I don't want to create a dedicated function to just convert a single parameter to another form.
I managed to split the string into an array but I don't know how to fill in empty slots with '', here's a simplified snippet:
const creditcard = '12345678123';
// need a one liner
const groups = creditcard.split(/(?<=^(?:.{4})+)/);
console.log(groups);
You could pad the string to minimum 16 characters with spaces, then trim the results
const creditcard = '12345678123';
// need a one liner
const groups = creditcard.padEnd(16, ' ').split(/(?<=^(?:.{4})+)/).map(v => v.trim());
console.log(groups);
Another option is to allocate an array with four elements and populate it with splices from your input:
const input = '111122223333444';
const output = Array(4).fill().map((_, i) => input.split('').splice(i*4, 4).join(''));
console.log(output);
// ["1111", "2222", "3333", "444"]
Use slice you can achieve your goal
Here is the code:
function splitToArray(n) {
const ret = [];
for(let i = 0; i < 16; i += 4) {
ret.push(n.slice(i, i + 4))
}
return ret;
}
console.log(splitToArray(''));
console.log(splitToArray('1234567812345678'));
console.log(splitToArray('12345678123'));

get numbers from string and use them to create an object javascript

So I would have the next string:
const string = "1,22, 28,40,4, 8,24,31,33"
var config = {
config_key: config_key,
location_key: null,
autoassign: 1,
}
I would need to create 9 objects from this string where the location_key: is equal with a value in the string, the other object prop. remains the same.
Split the string on /, ?/ (comma and optional space) then map those values to new objects, using config as a template and override the location_key using the string value.
const string = "1,22, 28,40,4, 8,24,31,33"
const config = {
config_key: 'config_key',
location_key: null,
autoassign: 1,
}
const parsed = string.split(/, ?/).map(location_key => ({
...config,
location_key
}))
console.info(parsed)
Since your question states...
where the location_key: is equal with a value in the string
I assumed you wanted to keep the values from the string as strings but if you want them treated as actual numbers (integers), use
location_key: parseInt(location_key, 10)
I would use a constructor to create each new instance of an Object:
const string = "1,22, 28,40,4, 8,24,31,33", config_key = 'testing';
function Config(locationKey){
this.config_key = config_key;
this.location_key = +locationKey;
this.autoassign = 1;
}
const nums = string.split(/\s*,\s*/), objs = [];
nums.forEach(n=>{
objs.push(new Config(n));
});
console.log(objs);

Categories

Resources