Explain Codes LogoExplain Codes Logo

Replace multiple characters in one replace call

javascript
prompt-engineering
functions
regex
Anton ShumikhinbyAnton Shumikhin·Oct 25, 2024
TLDR

To replace multiple characters in a single replace() call in JavaScript, we use a regular expression with a character class ([]) and the global (/g) flag. Take a look at this compact example:

let str = "FooBar123"; let newStr = str.replace(/[o1]/g, '_'); console.log(newStr); // "F__Bar_23"

The code substitutes every 'o' and '1' in str with an underscore ('_') in a single action.

One-to-one character replacement

Dynamically replace characters using a function callback

For replacements that are not uniform, a function callback delivers dynamic substitutions. Here is an illustration of using the replace() call with a replacement function:

let text = "Hello World! Is it #Sunny or _Cloudy?"; const replacements = { '#': 'very', '_': 'partly' }; let newText = text.replace(/#|_/g, (match) => replacements[match]); console.log(newText); // "Hello World! Is it verySunny or partlyCloudy?"

This approach is helpful if you need different replacements for different character matches.

Package the logic in a replaceAll function

To sustain code quality with repeated multi-character replacements, consider abstracting the logic into a reusable function:

function replaceAll(str, chars) { let re = new RegExp(Object.keys(chars).join('|'), 'g'); return str.replace(re, (match) => chars[match]); } let result = replaceAll("Hello! Is it #morning or _evening?", {'#': 'morning', '_': 'evening'}); console.log(result); // "Hello! Is it morning or evening?"

Chaining replace calls — when is it okay?

Contemplate the efficiency and readability of your code when deciding to chain multiple .replace() calls. Chaining is permissible for simple or fewer replacements. However, avoid it for lengthy and complex chains—think performance implications.

Combining regex and object mapping for versatile and scalable replacements

Efficiently juggle numerous, varied replacements by combining RegEx with object mapping:

let story = "The #turtle and the _hare."; let replacementMap = { '#': 'slow', '_': 'fast' }; let newStory = story.replace(/#|_/g, (matched) => replacementMap[matched]); console.log(newStory); // "The slow turtle and the fast hare."

This approach is scalable; it easily welcomes more replacement pairs without cluttering the code.

Advanced replacements: The icing on the cake

Flexible replacements using capturing groups and backreferences

Capturing groups (()) can be paired with backreferences in replacements, adding an extra layer of flexibility to your pattern matching:

let greeting = "Hi Anne, bye Anne."; let renamedGreeting = greeting.replace(/(Hi|bye) Anne/g, '$1 Mary'); console.log(renamedGreeting); // "Hi Mary, bye Mary."

Here, $1 corresponds to the first captured group: either "Hi" or "bye". Whichever way the wind blows!

Performance matters: Optimizing regex

When engaging in extensive text processing, do not skimp on optimizing your regex. Techniques such as precompiling your regex or using non-capturing groups (?:) can deliver noteworthy performance gains.

Regex asserting dominance: Lookahead and lookbehind assertions

Handle conditional replacements using lookahead ((?=...)) and lookbehind assertions ((?<=...)):

let prices = "Cost: $30 or €25"; let updatedPrices = prices.replace(/(?<=\$)30/g, '35').replace(/(?<=€)25/g, '30'); console.log(updatedPrices); // "Cost: $35 or €30"

This selectively updates prices based on currency, with zero disturbance to the rest of the text. Call it selective processing.

Before and after the one-shot seasoning:

Before: [🍞, 🧀, 🥬] After: [🍅, 🍖, 🌶️]

Each ingredient is substituted simultaneously, resulting in a new, flavorful combination in a single step. True culinary mastery!

References