Replace multiple strings between two indexes with in strings

I have a string. I want to replace substrings with in string. For each substring I have the starting and ending index. Using regex is out of scope.

So from let str = "I want chicken pizza and cheese pizza from point restaurant";

The expected result would be like this.

I want TYPE1 TYPE4 and TYPE1 pizza from point restaurant

let str = "I want chicken pizza and cheese pizza from point restaurant";

let roles = [{
    "start": 7,
    "end": 14,
    "typeId": "TYPE1",
    "type": "toppings",
    "text": "chicken"
  },
  {
    "start": 25,
    "end": 31,
    "typeId": "TYPE1",
    "type": "toppings",
    "text": "cheese"
  },
  {
    "start": 15,
    "end": 20,
    "typeId": "TYPE4",
    "type": "main ingredient",
    "text": "pizza"
  }
];

let styledStr = str;
roles.map(r => {
  const { start, end, typeId, text } = r;
  let strArr = str.split('');
  let removeStr = strArr.splice(start, end, typeId);
  styledStr = strArr.join('');
  console.log(styledStr);
});

3 thoughts on “Replace multiple strings between two indexes with in strings”

    1. Do not use a map if you do not need a
    2. No need to split unless you MUST use splice

    Method using start and end – note I sort the roles so we start at the highest position

    let str = "I want chicken pizza and cheese pizza from point restaurant";
    
    let roles = [{
        "start": 7,
        "end": 14,
        "typeId": "TYPE1",
        "type": "toppings",
        "text": "chicken"
      },
      {
        "start": 25,
        "end": 31,
        "typeId": "TYPE1",
        "type": "toppings",
        "text": "cheese"
      },
      {
        "start": 15,
        "end": 20,
        "typeId": "TYPE4",
        "type": "main ingredient",
        "text": "pizza"
      }
    ];
    
    let styledStr = str;
    roles.sort((a,b)=>b.start-a.start)
    roles.forEach(r => {
      const { start, end, typeId, text } = r;
      // Using substring because it is more readable and saves a split
      styledStr = styledStr.substring(0,start) + typeId + styledStr.substring(end)
      styledStr.slice(start,end,typeId)
    });
    console.log(styledStr)

    Method using text replace

    let str = "I want chicken pizza and cheese pizza from point restaurant";
    
    let roles = [{
        "start": 7,
        "end": 14,
        "typeId": "TYPE1",
        "type": "toppings",
        "text": "chicken"
      },
      {
        "start": 25,
        "end": 31,
        "typeId": "TYPE1",
        "type": "toppings",
        "text": "cheese"
      },
      {
        "start": 15,
        "end": 20,
        "typeId": "TYPE4",
        "type": "main ingredient",
        "text": "pizza"
      }
    ];
    
    let styledStr = str;
    roles.forEach(r => {
      const { start, end, typeId, text } = r;
      console.log(start,end,text)
      styledStr = styledStr.replace(text,typeId)
    });
    console.log(styledStr)
    Reply
  1. enter code here
    
    let roles = [{
            "start" : 7,
            "end" : 14,
            "typeId" : "TYPE1",
            "type" : "toppings",
            "text" : "chicken"
        }, 
        {
            "start" : 25,
            "end" : 31,
            "typeId" : "TYPE1",
            "type" : "toppings",
            "text" : "cheese"
        }, 
        {
            "start" : 15,
            "end" : 20,
            "typeId" : "TYPE4",
            "type" : "main ingredient",
            "text" : "pizza"
        }
    ];
    
    let str= `I want ${roles[0].typeId} ${roles[2].typeId} and ${roles[0].typeId}
     pizza from point restaurant`
    
    console.log(str)
    Reply
  2. By replacing certain words, you are changing the length of the String, and thus your indices start and end won’t hold the correct values anymore.

    Also, you always start with str.split(), meaning you override a previous replacement saved in styledStr. This is the reason why only one replacement is visible at the end.

    You should use Array.forEach() when performing actions based on the array’s items, and use Array.map() to get a new array mapped from the old one.
    Array.forEach() is what should be used here.

    You can fix your code by starting the replacement from the back.

    1. Sort roles in regards to either start or end in descending order
    2. Replace in styledStr
    3. Log to console
    let str = 'I want chicken pizza and cheese pizza from point restaurant';
    
    let roles = [
      {
        start: 7,
        end: 14,
        typeId: 'TYPE1',
        type: 'toppings',
        text: 'chicken'
      },
      {
        start: 25,
        end: 31,
        typeId: 'TYPE1',
        type: 'toppings',
        text: 'cheese'
      },
      {
        start: 15,
        end: 20,
        typeId: 'TYPE4',
        type: 'main ingredient',
        text: 'pizza'
      }
    ];
        
    let styledStr = str; // Start with raw string
    
    // 1. Sort `roles` (will be in ascending order; reverse to get descending order)
    roles.sort((o1, o2) => {
      if (o1.start < o2.start) return -1;
      if (o1.start == o2.start) return 0;
      return 1;
    }).reverse();
    
    // 2. Replace
    roles.forEach(i => {
      let arr = styledStr.split(''); // Transform `styledStr` instead of `str`
      arr.splice(i.start, (i.end - i.start), i.typeId);
      styledStr = arr.join(''); // Save transformation in `styledStr`
    });
    
    // 3. Log to Console
    console.log(styledStr);
    Reply

Leave a Comment