3

I have a string which contains characters that should be replaced once (at first appearance).

These characters are:

  • L => will be replaced with the lecture name
  • N => will be replaced with a name
  • D => will be replaced with a date

Example input:

L_N_L_D

Desired result (note that only the first L is replaced):

Math_Ex01_L_2018-10-05

My current code (simplified for the example):

let res = file_string.replace(/L|N|D/, x => {
  switch (x) {
    case 'L': return lecture;
    case 'N': return name;
    case 'D': return date;
    default: return x;
  }
});

What I get is this:

Math_L_N_D

If I change the regex to /L|N|D/g the second L will also be replaced which is not what I want.

How could this be implemented?

5
  • 2
    let res = file_string.replace('D', date).replace('N', name).replace('L', lecture) - note the order Commented Oct 8, 2018 at 11:52
  • I also tried this, but if the lecture contains the character 'N' for example the 'N' of the lecture will be replaced instead of the one in the file_string. Commented Oct 8, 2018 at 11:56
  • not if you do it in the order I did it ... note the order Commented Oct 8, 2018 at 11:57
  • The order is not fixed in my case, it can be dynamically changed by the user with a textfield. So if the name contains L I have the same problem as in the second comment. Commented Oct 8, 2018 at 12:01
  • oh ... OK ... thought it was fixed order :p Commented Oct 8, 2018 at 12:01

2 Answers 2

4

Put your replacements in a map, once a replacement is made, set map[x] to x:

let lecture = "Math";
let name = "Ex01";
let date = "2018-10-05";

let repl = {
  'L': lecture,
  'N': name,
  'D': date
};

let file_string = "L_N_L_D"

let result = file_string.replace(/[LND]/g, x => {
  let r = repl[x];
  repl[x] = x;
  return r;
});

console.log(result)

Apart from solving the problem at hand, this also greatly simplifies your replacement function (think adding new placeholders, for example).

That being said, a real solution to your problem would be to follow the @marsze's advice and use unambiguous placeholders, like {...}, in which case the whole enterprise becomes simply

 repl = {...as before...}
 result = subject.replace(/{(.+?)}/g, (_, x) => repl[x])
Sign up to request clarification or add additional context in comments.

Comments

4

Answering your general question "replace only the first occurrence of a character", you could do it like this:

var lecture = "Math";
var name = "Ex01";
var date = "2018-10-05";
var found = {};
var file_string = "L_N_L_D";
var filename_result = file_string.split("").map(function (character) {
  if (!found[character]) {
    found[character] = true;
    switch (character) {
      case "L": return lecture;
      case "N": return name;
      case "D": return date;
    }
  }
  return character;
}).join("");
console.log(filename_result);

You should probably explain where that odd format of the file_string comes from. Are there other similar use cases? Or is this just about this specific example? Understanding the original requirements would help a lot.

If the file_string is supposed to be a configurable format string, then it should be improved. A sequence which serves as a placeholder to be replaced should (or must) be different from a literal, e.g.:

var filename_format = "{L}_{N}_L_{D}";

1 Comment

Thank you, it works as expected :D Great answer and fast ^^

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.