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);
})

4
  • 1
    Looks just fine to me Commented Nov 8, 2018 at 0:30
  • If you wanted to do a global replace on entire thing you could try to convert to string and back stackoverflow.com/a/31262524/3254405 Commented Nov 8, 2018 at 0:36
  • 1
    str='xxx likes xxx and xxx' and list=['John', 'xxx movies', 'cooking'] probably won't work as intended ;) Commented Nov 8, 2018 at 0:38
  • haa :) I am using ### Commented Nov 8, 2018 at 0:41

2 Answers 2

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);

Sign up to request clarification or add additional context in comments.

2 Comments

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 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! :)
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);
})

Comments

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.