Replace text starting "@" with respetive variables in Object - Javascript

Viewed 47

I made this code trying to reproduce what i want to do in my Node JS API. I have "message" Array and "valueList" Object and i need to replace all text with "@" than have name of variables in "valueList" Object.

const message = [
    "Hi my name is @myname from @city",
    "Hi i'm a bot @botname from @city"
]

const valueList = {
    myname: "Roger",
    city: "Rio",
    botname: "Re"
}

/** This is my trying */

const replacedText = message
    .map((text) => text.replace("@myname",valueList.myname))
    .map((text) => text.replace("@botname",valueList.botname))
    .map((text) => text.replace("@city",valueList.city))

console.log(replacedText)

If i create one more variable in valueList i need to put one more .map in message, is possible to get automatically all object to replace all "message" ? i'm trying to do that, Thanks.

3 Answers

You can create a regular expression dynamically with the global flag, so that you can replace multiple instances of the replace text Example: "Hi my name is @myname from @city". @city is in @state.

const message = [
    "Hi my name is @myname from @city",
    "Hi i'm a bot @botname from @city"
]

const valueList = {
    myname: "Roger",
    city: "Rio",
    botname: "Re"
}

// map over messages
const replacedText = message.map(text) => {
  // map over key/values to replace
  return Object.keys(valueList).map(
    // create regexp with global to replace multiple if they exist
    (key) => text.replace(new RegExp(`@${key}`, 'g'), valueList[key])
 })

Another option is to create a dynamic regex with a capture group, and use an alternation | joining the keys from Object.keys(valueList) and use replace with a function.

In the replace function, you an index into the valueList object using the value of group 1 which will be either myname or myname or botname

The assembled regex looks like this and uses the global flag to replace all occurrences.

@(myname|city|botname)\b

The pattern matches:

  • @ Match literally
  • (myname|city|botname) Capture group 1, match any of the alternatives (referenced by g1 in the code for the replacement)
  • \b A word boundary to prevent a partial match

const message = [
  "Hi my name is @myname from @city",
  "Hi i'm a bot @botname from @city"
]

const valueList = {
  myname: "Roger",
  city: "Rio",
  botname: "Re"
}

const replacedText = message.map(s =>
  s.replace(
    new RegExp(`@(${Object.keys(valueList).join('|')})\\b`, 'g'),
    (_, g1) => valueList[g1]
  )
);

console.log(replacedText)

Object.keys(valueList).forEach((key) => {
   replacedText = message.replace('@'+key, valueList[key])
})

You can also use a reduce-map combination on the valueList

Related