How can I exchange elements of a string using the values of an object as argument?

Asked

Viewed 53 times

2

I have this code:

const operators = {
    plus : '+',
    minus : '-',
    multiplied : '*',
    divided : '/'
}

let question = 'What is 4 plus 6?';

let matchs = question.match(/\d|plus|minus|multiplied|divided/g);

matchs = matchs.join(''); 

console.log(matchs) // '4plus6'

And I’d like him to return something like '4+6'.

My idea was to use the replace, but I don’t know how I could pass the + as argument using objects.

My knowledge of objects is very little, so I would like to be able to understand a little more about, because I see resolutions where a large number of if else can be replaced using objects.

2 answers

3


One option is to use replace, passing as the second parameter a function of callback:

const operators = {
    plus: '+',
    minus: '-',
    multiplied: '*',
    divided: '/'
};

let question = 'What is 4 plus 6? And 4 minus 6, 4 multiplied 6, 4 divided 6';

let s = question.replace(/\b(plus|minus|multiplied|divided)\b/g, function(match, op) {
    return operators[op];
});

console.log(s) // What is 4 + 6? And 4 - 6, 4 * 6, 4 / 6

I use the shortcut \b (word Boundary, if you want a more detailed explanation about it, see here) to specify that before and after the text there is no alphanumeric character (so I only take the words "plus", "Minus", etc, when they are "isolated" from the text - if you have something like "Multiplus", the regex ignores).

The words are in parentheses to form a catch group (and also because of the order of precedence, see here and here how does it matter).

Then I pass a function of callback received as parameters the match and the first capture group (which I called op). Then, just return the symbol corresponding to the text that was captured, which is in the first group (in the variable op). The result of the function is what will be used in the substitution, i.e., it exchanges "plus" for "+", "Minus" for "-" and so on.

Remember that the rest of the text (the "What is" and the commas I put in the example) is not removed.


If you want words to be replaced only if you have numbers before and after, you can switch to:

const operators = {
    plus: '+',
    minus: '-',
    multiplied: '*',
    divided: '/'
};

let question = 'What is 4 plus 6? And 4 minus 6, 4 multiplied 6, 4 divided 6, plus without numbers.';

let s = question.replace(/(\d+)\s*\b(plus|minus|multiplied|divided)\b\s*(\d+)/g, function(match, n1, op, n2) {
    return `${n1}${operators[op]}${n2}`;
});

console.log(s) // What is 4+6? And 4-6, 4*6, 4/6, plus without numbers.

Now I have included 2 more capture groups with \d+ (one or more digits) and with optional spaces (\s* - zero or more spaces), then the function of callback should receive further arguments to match these additional groups (n1 is the number before the operation, op is the text and n2 is the number after the operation).

On the return of the function I change the text for the symbol of the operation and keep the numbers. I didn’t put space between them, but if you want a space, just do return `${n1} ${operators[op]} ${n2}`;.

2

Of course, you can use regular expression, as suggested by another answer, but you can also divide the phrase by spaces and exchange the "operator-words" for the respective symbols.

Behold:

const operators = {
  plus: '+',
  minus: '-',
  multiplied: '*',
  divided: '/'
};

const question = 'What is 4 plus 6? And 4 minus 6, 4 multiplied 6, 4 divided 6';

const symbolified = question
  .split(' ')
  .map((word) => operators[word] || word)
  .join(' ');

console.log(symbolified); // What is 4 + 6? And 4 - 6, 4 * 6, 4 / 6

Basically, the original string is divided into one array of words. For each of these words, we check for correspondence in the object operators. If it does not exist, the expression operators[word] returns undefined, so that word word is used as fallback by the operator ||, that makes there short-circuit evaluation.

I can’t tell if this is more or less performative, but if it’s something important, it’s worth seeing again later. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.