0

I have this variable:

WelcomeText = 'Hi $0! Welcome to $1!';

And I am trying to create this function:

translate(WelcomeText, 'Daniel', 'Budapest');

Which should return this:

'Hi Daniel! Welcome to Budapest!'

I have tried to make this function which should support unlimited arguments to replace:

export const translator = (str, ...args) => {
  let translate = args.map((item, index) => {
    let stringToReplace = '$' + index;
    let result = str.replace(stringToReplace, item);
    return result;
  });

  console.log(translate);
};

But that gives me this:

["Hi Daniel! Welcome to $1", "Hi $0! Welcome to Budapest"]

Not sure how to explain it more than this, but I am out of words so I hope u can understand my problem with above :)

What am I doing wrong here, and what do I need to do to reach my desired result?

1
  • map always creates a new array of the same length, but you want to return a string. Commented Mar 20, 2020 at 10:37

6 Answers 6

2

You can simply use forEach instead

let WelcomeText = 'Hi $0! Welcome to $1!';

const translator = (str, ...args) => {
  args.forEach((item, index) => {
    let stringToReplace = '$' + index;
    str= str.replace(stringToReplace, item);
  });
  console.log(str);
};

translator(WelcomeText, 'Daniel', 'Budapest');

Since you're using map in your original code so it returns a new string on every iteration and you endup getting an array of string, where in actual you need to get a string with all $(index) instance replaced so you should be using the replaced string on next iteration onwards

Sign up to request clarification or add additional context in comments.

2 Comments

Yes! I will go with this! :D Thank you very much. Works wonderful! Do you have any advice on how to implement a error handling for this function? I was thinking about just comparing the original string with the translated one to see any difference, but is there more I could do?
@OsgarSchölander always welcome, i am not clearly understanding what exactly error handling means to you as your last statement means you just want to check whether it has changed anything in string or not ( that comes under unit testing of your function as this is most likely due to problem in logic not in syntax ).
2

You could take a function as replacement parameter and search for the index of the string.

const
    translate = (string, ...items) => string.replace(/\$(\d+)/g, (_, i) => items[i]),
    text = 'Hi $0! Welcome to $1!';


console.log(translate(text, 'Daniel', 'Budapest'));

Comments

1

map always creates a new array of the same length, but you want to return a string. You could use reduce instead with the text as the initial value:

var welcomeText = 'Hi $0! Welcome to $1!';

const translate = (t, ...args) => args.reduce((a, x, i) => a.replace(`$${i}`, x), t);

console.log(translate(welcomeText, 'Daniel', 'Budapest'));

Comments

1

The problem is that Array#map creates an array, so each replacement is treated as a separate thing to replace, so first you replace $0 and leave $1 but next time you're replacing from the original string and only replace $1 but leave $0.

Since you don't need an array as a result, you can use Array#forEach to just keep updating the str every time:

const translator = (str, ...args) => {
  
  let translate = args.forEach((item, index) => {
    let stringToReplace = '$' + index;
    str = str.replace(stringToReplace, item);
  });

  console.log(str);
};

const WelcomeText = 'Hi $0! Welcome to $1!';

translator(WelcomeText, 'Daniel', 'Budapest');

Alternatively, you could use Array#reduce and use the resulting value:

const translator = (str, ...args) => {
  
  let translate = args.reduce((result, item, index) => {
    let stringToReplace = '$' + index;
    return result.replace(stringToReplace, item);
  }, str);

  console.log(translate);
};

const WelcomeText = 'Hi $0! Welcome to $1!';

translator(WelcomeText, 'Daniel', 'Budapest');

You can also String#replace with a function as a replacer parameter, which will allow you to dynamically determine what the replacement would be:

const translator = (str, ...args) => {
  let translate = str.replace(
    /\$(\d+)/g, //match a pattern that has $ followed by a number, capture the number
    (match, placeholderNumber) => args[placeholderNumber] //replace with corresponding the value from args
  )

  console.log(translate);
};

const WelcomeText = 'Hi $0! Welcome to $1!';

translator(WelcomeText, 'Daniel', 'Budapest');

Comments

0

Try this

let name = args[0];
let place = args[1];

let message = 'Hi ${name}, welcome to ${place}`;

1 Comment

Yes, but that is not as dynamic as I need it to be. Therefore my try to loop through it :)
0

I would pass to translator array of arrays, like this:

const welcome = "Hi $0! Welcome to $1!";

const returnString = (str, name, city) =>
  str.replace("$0", name).replace("$1", city);

const translator = (str, arr) => {
  return arr.map(([name, city]) => returnString(str, name, city));
};

console.log(
  translator(welcome, [
    ["John", "NY"],
    ["Sara", "LA"],
    ["Bill", "SF"]
  ])
);

output:  ["Hi John! Welcome to NY!", "Hi Sara! Welcome to LA!", "Hi Bill! Welcome to SF!"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.