10

Is there a function that can replace a string within a string once at a specific index of the string? Example:

var string1="my text is my text and my big text";
var string2="my";
string1.replaceAt(string2,"your",2);

and the resultant output would be "my text is my text and your big text"

it freelance
  • 101
  • 6

5 Answers5

6

You can do this with a little bit of manipulation, not requiring any regex.

I used this function to fetch the position (index) of another string within a string.

From there, it's as simple as returning a substring from the beginning to the found index, injecting your replacement, and then returning the rest of the string.

function replaceAt(s, subString, replacement, index) {
  const p = s.split(subString, index+1).join(subString);
  return p.length < s.length ? p + replacement + s.slice(p.length + subString.length) : s;
}

console.log(replaceAt("my text is my text and my big text", "my", "your", 2))
console.log(replaceAt("my text is my text and that's all", "my", "your", 2))
console.log(replaceAt("my text is my my my my text", "my", "your", 2))
caub
  • 2,709
  • 2
  • 28
  • 31
Blue
  • 22,608
  • 7
  • 62
  • 92
  • @mplungjan The main issue with regex, is you're assuming that the substring doesn't contain any regexp characters that need escaping. This can cause some nasty bugs down the road, for some strings that may contain periods or stars. Additionally, to create a comparable function to your own, would require this escaping, and would slow things down considerably: https://jsperf.com/string-index-replacements – Blue Oct 20 '18 at 15:58
  • Which is good to know and handle when needed. There will be no need for performance checking for simple sporadid changing. If there is, then yes, one should handle that – mplungjan Oct 20 '18 at 16:01
  • always prefer `str.slice(..)` over `str.substring(..)` because it's more consistent (negative indexes, ..) and behave like `arr.slice(..)`. [`str.substr(..)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) shouldn't be used as described – caub Oct 28 '18 at 09:56
2

There's not a built-in way to do that, but you can exploit the fact that .replace() can be passed a function:

let count = 0;
console.log("my text is my text and my big text".replace(/my/g, function() {
  if (count++ === 2) return "your";
  return "my";
}));
The function is passed the matched string and any groups as arguments, but in this case that's not really necessary.
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Pointy
  • 405,095
  • 59
  • 585
  • 614
2

Here is a prototype version

String.prototype.replaceAt = function(str1,str2,pos) {
  let count = 0;
  let re = new RegExp(str1,"g");
  return this.replace(re, function() {
    return (count++ === pos) ? str2 : str1;
  });
}
console.log("my text is my text and my big text".replaceAt("my","your",2))
mplungjan
  • 169,008
  • 28
  • 173
  • 236
2

Beside the use of a function for replacement, you could use the given variable for the position directly for decrementing and take this value as check for replacement or not.

const replace = (string, s, r, p) => string.replace(new RegExp(s, 'g'), m => p-- ? m : r);
var string = 'my text is my text and my big text';

console.log(replace(string, 'my', 'your', 2));
Blue
  • 22,608
  • 7
  • 62
  • 92
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

As we need to look for index where we need to replace our word and for other words we don't need any change so used "map". Converted string to array by split and using map returned each element as it is and just replaced word when reached to specific index (by logic of index-- == 0). Finally joined back array to string.

    function replace(text, strFrom, strTo, index) {
     return text.split(' ')
                   .map(d => d == strFrom && index-- == 0
                                 ? strTo 
                                 : d)
                   .join(' ')
    }
    
    var string = 'my text is my text and my big text';
    
    string = replace(string, 'my', 'your', 2)
    
    console.log(string)
Nitish Narang
  • 4,124
  • 2
  • 15
  • 22
  • 1
    Should try to use `===`, as it's a bit more safe, and in this case can easily be swapped: https://eslint.org/docs/rules/eqeqeq – Blue Oct 22 '18 at 05:37