2

I have a lot of strings and I am replacing "xxx" with elements of an array. These arrays can have different lengths. My code is currently working but I am not sure if this is the best way. How would you do it or would you optimize it?

var items = [{
    str: 'This is xxx an he is xxx years old ',
    list: ['Frank', '14']
  },
  {
    str: 'xxx and xxx are xxx ',
    list: ['George', 'John', "studying"]
  }
]


items.forEach(item => {
  item.list.forEach(s => {
    item.str = item.str.replace("xxx", s)
  })
  console.log(item.str);
})
eag845
  • 1,013
  • 1
  • 11
  • 16

2 Answers2

1

If the strings are too long or if the replacements can have the substring "xxx" in them, then you'd be better off using a regex with the global modifier and use the callback of replace to select an item from the array using an index:

items.forEach(item => {
  let index = 0;
  item.str = item.str.replace(/xxx/g, m => item.list[index++]);
});

Otherwise, your solution is just fine.

Notes:

1- You may want to check if index goes beyond item.list.length in case there are more xxx than there are items in item.list. A safe solution would be:

item.str = item.str.replace(/xxx/g, m => item.list[index++] || m);

Which replaces by m if item.list[index++] is undefined.

2- If you don't care about mutating item.list, then the whole solution could be a lot shorter by using shift instead of the index:

items.forEach(item => item.str.replace(/xxx/g, m => item.list.shift() || m));

Example:

var items = [{
    str: 'This is xxx an he is xxx years old ',
    list: ['Frank', '14']
  },
  {
    str: 'xxx and xxx are xxx ',
    list: ['George', 'John', "studying"]
  }
]


items.forEach(item => {
  let index = 0;
  item.str = item.str.replace(/xxx/g, m => item.list[index++]);
})

console.log(items);
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • Great, your code is simpler. I am really using "###", my strings may have 15-25 words, and 4-7 "###". Said that, would you use my method or regex ? I think regex may be faster. – eag845 Nov 08 '18 at 05:55
  • @eag845 I think you should tell me that. You already have tons of data to test it on. Try running both and see who's the fastest! :) – ibrahim mahrir Nov 08 '18 at 14:04
0

You can get rid off one of the for each with this approach.. Here you are searching for all "xxx" with regexp in "str" and use array shift() method to return and remove first element from the "list" array..

var items = [{
    str: 'This is xxx an he is xxx years old ',
    list: ['Frank', '14']
  },
  {
    str: 'xxx and xxx are xxx ',
    list: ['George', 'John', "studying"]
  }
]


items.forEach(item => {

    item.str = item.str.replace(/xxx/g,function (x) {
        return item.list.shift();
    });

    // item.list.forEach(s => {
    //   item.str = item.str.replace("xxx", s)
    // })

  console.log(item.str);
})
boateng
  • 910
  • 11
  • 21