'loop over string, add words to string, return string
I have a plainText object. I also have an array of objects. In that array of objects, each object contains offset and length keys.
I want to loop over my plainText string, insert the proper words into the string at certain offsets and then return that string.
Here is my code below
const plainText = "Hey name your food is ready, , your food has your name on it"
expected output below
mergeValues = [
{message: "Hey Keith your salmon is ready, your food has your name on it"},
{message: "Hey Kelly your pizza is ready, your food has your name on it"},
{message: "Hey Ed your hamburger is ready, your food has your name on it"},
{message: "Hey Shelby your sushi is ready, your food has your name on it"}
]
const people = [
{ name: "keith", food: "salmon"},
{ name: "kelly", food: "pizza"},
{ name: "ed", food: "hamburger"},
{ name: "shelby", food: "sushi"}
]
const locations = [
{offset: 4, length: 4, field: 'name'},
{offset: 13, length: 4, field: 'food'}
]
Here I am mapping over people, creating an object, then running a forEach on locations, and finally returning that object back to the map to let it run again on the next person in people array. Im pretty sure my main issue is that I am Rewriting over the object everytime in the forEach loop instead of modifying the string, saving that value, then modifying that string again, saving value etc.....
const mergeValues = people.map((person) => {
const messageObj = {message: ""};
locations.forEach((location) => {
if(Object.keys(person).includes(location.field)) {
messageObj.message = plainText.substring(0, location.offset + 1) + person[location.field] + plainText.substring(location.length + location.offset + 1, plainText.length)
}
})
return messageObj
Solution 1:[1]
If you can change the plainText string to use custom vars, you can create your own function to fill those vars using regular expressions
const template =
"Hey {name} your {food} is ready, your food has your name on it";
const variables = [
{ name: "keith", food: "salmon" },
{ name: "kelly", food: "pizza" },
{ name: "ed", food: "hamburger" },
{ name: "shelby", food: "sushi" }
];
function renderTemplate(template, variables) {
let result = template;
for (let [key, value] of Object.entries(variables)) {
result = result.replace(new RegExp(`{${key}}`, "g"), value);
}
return result;
}
const results = variables.map((variableValues) =>
renderTemplate(template, variableValues)
);
console.log(results);
With this approach you can even put the same variable in multiple places, you control the variable location using your own syntaxs ({varName}
in this case).
Less complexity, you don't need to count positions, that approach will make adding new vars harder.
const template =
"Hey {name} your {food} is ready, your food has your name on it - {name}"
Will compile to
"Hey Keith your salmon is ready, your food has your name on it - Keith"
just adding {name}
to the template
CodeSandbox: https://codesandbox.io/s/loving-cherry-jnwt5s?file=/src/index.js
Solution 2:[2]
Your solution is pretty complex, try with String.replace, like this:
const mergeValues = people.map((person) => {
const messageObj = {message: plainText};
for(const key in person){
messageObj.message = messageObj.message.replace(key, person[key])
}
return messageObj
})
Solution 3:[3]
You can simply use map
, reduce
and replace
to achieve the result as:
const plainText = 'Hey name your food is ready';
const people = [
{ name: 'keith', food: 'salmon' },
{ name: 'kelly', food: 'pizza' },
{ name: 'ed', food: 'hamburger' },
{ name: 'shelby', food: 'sushi' },
];
const locations = [
{ offset: 4, length: 4, field: 'name' },
{ offset: 14, length: 4, field: 'food' },
];
const mergeValues = people.map((person) => {
return locations.reduce((acc, { field }) => {
return acc.replace(field, person[field]);
}, plainText);
});
console.log(mergeValues);
Solution 4:[4]
You can try this with replace.
const plainText = "Hey name your food is ready, your food has your name on it"
const people = [
{ name: "keith", food: "salmon"},
{ name: "kelly", food: "pizza"},
{ name: "ed", food: "hamburger"},
{ name: "shelby", food: "sushi"}
]
const locations = [
{offset: 4, length: 4, field: 'name'},
{offset: 14, length: 4, field: 'food'}
]
const mergeValues = people.map((person) => {
let plainTextLength = plainText.length;
let messageObj = {message:plainText};
locations.map((location) => {
let lengthOffset = 0;
if(messageObj.message.length > plainTextLength){
lengthOffset = messageObj.message.length - plainTextLength;
messageObj.message = messageObj.message.replace(messageObj.message.substring(location.offset + lengthOffset, location.offset + location.length + lengthOffset), person[location.field]);
} else if (messageObj.message.length < plainTextLength) {
lengthOffset = plainTextLength - messageObj.message.length;
messageObj.message = messageObj.message.replace(messageObj.message.substring(location.offset - lengthOffset, location.offset + location.length - lengthOffset), person[location.field]);
} else {
messageObj.message = messageObj.message.replace(messageObj.message.substring(location.offset, location.offset + location.length), person[location.field]);
}
})
return messageObj
});
console.log(mergeValues);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Link Strifer |
Solution 2 | Bane2000 |
Solution 3 | decpk |
Solution 4 |