Replace certain values in a string based on a mapping - JS - javascript

I have a string with words followed by a colon. I need to replace the colon words in that string with values from an object. I was able to extract out the colon words but not sure on the best way to replace it in the string.
This is what I have:
const string = 'This is :state :buttonName by :name';
const buttonName = 'button link';
const data = {
state: 'Alabama',
name: 'Arun'
}
const res = string.match(/:[a-zA-Z]+/g).map(i => i.replace(':', ''))
console.log(res)
// This is Alabama button link by Arun
End result should be
This is Alabama button link by Arun
Please advice.

First of all, you need to move const buttonName = 'button link'; to the array.
You need to use String#replace, but also you need to capture the part of the regex after : and actually use the Group #1 value as key to get the right data value.
Besides, you need to check if the extracted key is inside the dictionary to avoid issues.
You can use
const string = 'This is :state :buttonName by :name';
const data = {
buttonName: 'button link',
state: 'Alabama',
name: 'Arun'
}
const res = string.replace(/:([a-zA-Z]+)/g, (m, i) => i in data ? data[i] : m)
console.log(res)

You can split the string and then call array map to replace words and the join to final string
const str= 'This is :state :buttonName by :name';
str.split(' ').map(a => {
if(a.startsWith(":"))
return data[a.replace(":","")];
return a;
}).join(' ');

If you've already stripped the ":" from the string you can just iterate your object keys and replace them with the respective values.
...
const res = string.match(/:[a-zA-Z]+/g).map(i => i.replace(':', ''))
for (const [key, value] of Object.entries(data)) {
res = res.replaceAll(key, value);
}

Wiktor's answer is good. But if it needs to replace the global variable as well, we can write the code as belows.
const res = string.replace(/:([a-zA-Z_]+)/g, (m, i) => data[i] ?? eval(i) ?? m);
console.log(res)
This code didn't do exception handling yet. It should be in consideration. So we can define a replacer function handling exception
const replacer = (m, i) => {
try {
return data[i] ?? eval(i);
} catch {
return m;
}
}
const res = string.replace(/:([a-zA-Z_]+)/g, replacer);

Related

Replace words with array map

I have this array
(2) ['beginning=beginner', 'leaves=leave']
and this string
its beginner in the sounds leave
which i have converted to an array
var words = text.split(' ');
i want to replace beginner with beginning and leave with leaves it can be any dynamic words but for now it has only two elements i can replace it within for loop. Is it possible with map method.
this.words.map((words, i) => console.log(words));
Note: Only first instance should get replaced.
Any Solution Thanks
does this correct with your question ?
const arrString = ["beginning=beginner", "leaves=leave", "sound=sounds"];
let string = "its beginner in the sounds leave";
arrString.forEach((mapString) => {
const stringArr = mapString.split("=");
string = string.replace(stringArr[1], stringArr[0]);
});
console.log("string", string);
// "its beginning in the sound leaves"
You can do it in without a nested loop too if you compromise with space.
Here is a solution which creates a mapping object for replacement values and uses array methods like map(),forEach(),join() and string method like split()
const arrString = ["beginning=beginner", "leaves=leave", "sound=sounds"];
let string1 = "its beginner in the sounds leave beginner";
const replaceObj = {};
const arrBreaks = arrString.forEach(x => {
let els = x.split("=");
replaceObj[els[1]] = els[0]; });
const ans = string1.split(' ').map((x) => {
if(x in replaceObj) { let val = replaceObj[x]; delete val; return val; }
return x;
}).join(' ');
console.log(ans);

Using trim more than once in an array JS

I have a snippet of code where I am trying to parse a longer string with special characters into an array with no spaces or special characters.
input: name: this is some stuff, name2: this is more stuff
desired output: [name,this is some stuff,name2,this is more stuff]
current output: z.trim isn't a function
function parseOrder(custOrder) {
const custOrderArr = custOrder.split(',');
const trimedArr = custOrderArr.map((x) => x.trim());
const numberArr = trimedArr.map((y) => y.split(':'));
const processArr = numberArr.map((z) => z.trim());
console.log(processArr);
}
Why does trim work the first time and not the second?
You can not trim an array. But you could map the array and trim the values.
This result features Array#flatMap for preventing arrays with pairs.
function parseOrder(custOrder) {
return custOrder
.split(',')
.flatMap(y => y.split(':').map(x => x.trim()));
}
var input = 'name: this is some stuff, name2: this is more stuff ';
console.log(parseOrder(input));
Try to split by two signs, then trim your elements:
const result = str.split(/[\:,]+/).map(s => s.trim());
An example:
let str = 'test: It is me, test2: it is me 2 ';
console.log(str.split(/[\:,]+/).map(s => s.trim()));

Camelcase string to normal string

How to change NoOfSAP => No Of SAP? I have trying the replace method but it says undefined.
function unCamlelCase(result) {
return result.key.replace(/([^A-Z]*)([A-Z]*)([A-Z])([^A-Z]*)/g, '$1 $2 $3$4')
.replace(/ +/g, ' ');
};
How can I change the result key values camel case to normal string?
if (exactMatch) {
const { ...response } = json[0];
const result = Object.keys(response).reduce((acc, key) => {let newKey = key.charAt(0).toUpperCase() + key.slice(1);
return acc;
}, {});
You could use the following expression with a few helper methods to clean up the output:
"NoOfSAP".split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
This will match all upper case letters followed by one or more lower-case letters and split each chunk into an array. .filter(Boolean) is then used to remove any empty strings in the array and .join is then used to add spaces between the strings in the array.
See example below:
const getWords = wrd =>
wrd.split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
console.log(getWords("NoOfSAP")); // No Of SAP
console.log(getWords("ThisIsAWord")); // This Is A Word (notice how it will split individual letters such as A)
console.log(getWords("IAmAHuman")); // I Am A Human
console.log(getWords("JSIsGreat")); // JS Is Great (notice how it understands JS and Is are two seperate words and doesn't give JSI s Great)
As per your question about changing the keys in your object to the "uncamelcased" keys you can use .map with Object.keys to generate your result:
const getWords = wrd =>
wrd.split(/([A-Z][a-z]+)/).filter(Boolean).join(' ');
const obj = {
"NoOfSAP": 1,
"NoOfBUN": 2,
"NoOfBRE": 3,
"NoOfPEA": 4
}
const result = Object.keys(obj).map(getWords);
console.log(result);
You can go that way:
const camelToWords = (camelCaseWord) => camelCaseWord
.replace(/([A-Z]+)/g, " $1")
.replace(/([A-Z][a-z])/g, "$1");
There is also possibility to use existing libraries like lodash:
const _ = require('lodash');
console.log(_.startCase('abcDef'));
// result: Abc Def

What is a concise way to parse a javascript string that is a comma delimited list of key=value pairs?

I'm trying to parse a string into a JavaScript array or map. The string I'm trying to parse looks like:
"{key1=value1, key2=value2, key3=value3}"
The code I currently have works, but it's a bit lengthy.
str = "{key1=value1, key2=value2, key3=value3}";
str = str.replace(/{/g, '');
str = str.replace(/}/g, '');
var strMap = {};
str.split(', ').forEach(function(x) {
var arr = x.split('=');
strMap[arr[0]] = arr[1];
});
console.log(strMap)
That gets me what I want, but it's not very clean. Someone suggested I use JSON.parse, but it doesn't seem to work as the string isn't in valid JSON format.
Is there a concise way to do it so I'm not manually parsing the string?
You could split the string by comma and whitespace and splir key/value pairs for the properties of the new object. The result has strings as value.
const getPair = ([k, v]) => ({ [k]: v });
var string = "{key1=value1, key2=value2, key3=value3}",
result = Object.assign(...string
.slice(1, -1)
.split(/,\s+/)
.map(p => getPair(p.split('=')))
);
console.log(result);
Or take (upcoming) Object.fromEntries.
const getPair = ([k, v]) => ({ [k]: v });
var string = "{key1=value1, key2=value2, key3=value3}",
result = Object.fromEntries(string
.slice(1, -1)
.split(/,\s+/)
.map(p => p.split('='))
);
console.log(result);
You can use some ES6 features to pretty easily put together a decent naive solution (format as outlined by your example).
const example = "{key1=value1, key2=value2, key3=value3}";
const stripped = example.substring(1, example.length - 1);
const map = stripped.split(",")
.map(pair => pair.trim())
.reduce((result, current) => {
const [key, value] = current.split("=");
return {
...result,
key: value
};
}, {});

How to fetch a value from a string in javascript?

I want to fetch a particular value from a javascript string without using methods like indexOf or substr. Is there any predefined method of doing so?
For e.g., I have a string,
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
I want to fetch the value of c from above string, how can I achieve it directly?
You can try with:
str.split('|').find(value => value.startsWith('c=')).split('=')[1]
You can also convert it into an object with:
const data = str.split('|').reduce((acc, val) => {
const [key, value] = val.split('=');
acc[key] = value;
return acc;
}, {});
data.c // 3
In this case, use split:
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var parts = str.split('|');
var value = parts[2].split('=')[1];
console.log(value);
Or maybe map it, to get all values to work with afterwards:
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var values = str.split('|').map(e => e.split('='));
console.log(values);
Using regex can solve this problem
const str = "a=1|b=2|c=3|d=4|e=5|f=6";
const matches = str.match(/c=([0-9]+)/);
console.log(matches[1]);
Ref:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
Try this -
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
str.split('|')[2].split('=')[1];
You could turn that string into an associative array or an object
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var obj = {}; //[] for array
str.split("|").map(o => {
var el = o.split("=");
obj[el[0]] = el[1];
})
console.log(obj.a)
console.log(obj.b)
console.log(obj.c)
I suggest first splitting and mapping into some form of readable data structure. Finding by string is vulnerable to typos.
const mappedElements = str
.split('|')
.map(element => element.split('='))
.map(([key, value]) => ({ key: value }));
Array filter method can be memory efficient for such operation.
var cOutput = str.split('|').filter( (val) => {
const [k,v] = val.split('=');
return k=='c' ? v : false }
)[0].split('=')[1];
See Array Filter

Categories