436

I have a string, let's say Hello world and I need to replace the char at index 3. How can I replace a char by specifying a index?

var str = "hello world";

I need something like

str.replaceAt(0,"h");
  • 79
    What's weird is that str[0] = 'x' doesn't seem to throw any errors, yet doesn't have the desired effect! – Michael Nov 15 '13 at 19:43
  • 3
    @Michael with that you would get the index at 0, set it to 'x', that statement at itself would return the new value; 'x'. but all of it doesnt change the origional, so its perfectly valid, just not what you expected. its not a reference – Paul Scheltema Nov 21 '13 at 14:46
  • 6
    @Michael it does if "use strict" is activated: Uncaught TypeError: Cannot assign to read only property '0' of string 'hello world' (at least in webkit browsers) – Jan Turoň Oct 27 '16 at 20:15

20 Answers 20

499

In JavaScript, strings are immutable, which means the best you can do is create a new string with the changed content, and assign the variable to point to it.

You'll need to define the replaceAt() function yourself:

String.prototype.replaceAt=function(index, replacement) {
    return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}

And use it like this:

var hello="Hello World";
alert(hello.replaceAt(2, "!!")); //should display He!!o World
  • 75
    Note that it's generally not a good idea to extend base JavaScript classes. Use a plain utility function instead. – Ates Goral Sep 16 '09 at 5:40
  • 78
    I must ask why? Prototype support is there for this purpose. – Cem Kalyoncu Sep 16 '09 at 6:58
  • 26
    @CemKalyoncu: It can make code play bad with other libraries. But I haven't ever been bitten by that myself. – alex Jul 21 '11 at 4:53
  • 6
    @alex: you are right about that, you really need to check if that function exists before doing it. But still even if it does, it should do exactly the same operation. – Cem Kalyoncu Jul 21 '11 at 10:11
  • 66
    I disagree, even if you detect whether the function exists a later library may still use/create a similar function -- 2 bad ideas making a worse one. In general, just never play around with other peoples code (include the core system). Create a new function. – martyman Jun 5 '12 at 1:05
74

There is no replaceAt function in JavaScript. You can use the following code to replace any character in any string at specified position:

function rep() {
    var str = 'Hello World';
    str = setCharAt(str,4,'a');
    alert(str);
}

function setCharAt(str,index,chr) {
    if(index > str.length-1) return str;
    return str.substr(0,index) + chr + str.substr(index+1);
}
<button onclick="rep();">click</button>

52

You can't. Take the characters before and after the position and concat into a new string:

var s = "Hello world";
var index = 3;
s = s.substr(0, index) + 'x' + s.substr(index + 1);
  • Actually, yes, you can, but it would be an overkill. You could set up a regular expression to skip the first index - 1 characters and match the character at the index. You can use String.replace with that regular expression to do a direct, in-place replacement. But it's an overkill. So, in practice you can't. But in theory, you can. – Ates Goral Sep 16 '09 at 5:42
  • 11
    @Ates: The replace function doesn't do an in-place replacement, it creates a new string and returns it. – Guffa Sep 16 '09 at 5:55
  • MDN suggests to use String.prototype.substring over String.prototype.substr. – Mikemike Feb 10 at 11:55
29

There are lot of answers here, and all of them are based on two methods:

  • METHOD1: split the string using two substrings and stuff the character between them
  • METHOD2: convert the string to character array, replace one array member and join it

Personally, I would use these two methods in different cases. Let me explain.

@FabioPhms: Your method was the one I initially used and I was afraid that it is bad on string with lots of characters. However, question is what's a lot of characters? I tested it on 10 "lorem ipsum" paragraphs and it took a few milliseconds. Then I tested it on 10 times larger string - there was really no big difference. Hm.

@vsync, @Cory Mawhorter: Your comments are unambiguous; however, again, what is a large string? I agree that for 32...100kb performance should better and one should use substring-variant for this one operation of character replacement.

But what will happen if I have to make quite a few replacements?

I needed to perform my own tests to prove what is faster in that case. Let's say we have an algorithm that will manipulate a relatively short string that consists of 1000 characters. We expect that in average each character in that string will be replaced ~100 times. So, the code to test something like this is:

var str = "... {A LARGE STRING HERE} ...";

for(var i=0; i<100000; i++)
{
  var n = '' + Math.floor(Math.random() * 10);
  var p = Math.floor(Math.random() * 1000);
  // replace character *n* on position *p*
}

I created a fiddle for this, and it's here. There are two tests, TEST1 (substring) and TEST2 (array conversion).

Results:

  • TEST1: 195ms
  • TEST2: 6ms

It seems that array conversion beats substring by 2 orders of magnitude! So - what the hell happened here???

What actually happens is that all operations in TEST2 are done on array itself, using assignment expression like strarr2[p] = n. Assignment is really fast compared to substring on a large string, and its clear that it's going to win.

So, it's all about choosing the right tool for the job. Again.

  • 3
    Moved your test to jsperf, with vastly different results: jsperf.com/string-replace-character. It's all about choosing the right tool for the job ;) – colllin Oct 30 '14 at 3:11
  • @colllin: I absolutely agree. So I almost literally cloned the tests from jsfiddle to jsperf. However, aside from using the right tool, you have to do it in the right way. Pay attention to the problem, we're talking about what will happen if we have to make quite a few replacements in an algorithm. The concrete example includes 10000 replacements. This means one test should include 10000 replacements. So, using jsperf, I got quite consistent results, see: jsperf.com/…. – OzrenTkalcecKrznaric Oct 30 '14 at 9:22
  • 1
    this is why i don't like javascript. such frequent, intuitive, obvious use cases aren't provisioned for. You'd think it would occur to the writers of javascript that people may want to substitute characters within strings, and that they'd decide to put in convenience methods into the language. – ahnbizcad Mar 26 '15 at 4:43
  • 1
    @colllin did something different to OzrenTkalcecKrznaric. OzrenTkalcecKrznaric made the assumption that the string is static and and the split can be optimized before the runs. Which is not necessarily true. if you have to split at every run then the substring approach is about twice-4x faster on small strings, and only faster the bigger the string gets. In my opinion this makes the substring the better implementation for most use cases, barring large numbers of changes on a large static string. – WiR3D Mar 2 '16 at 15:33
  • 3
    The problem is that on test2 the split and join are outside the for loop, where you compare single char replacement with a multiple one (unfair), the first method is faster for single replacements and the second one is better for chained replacements one after another – Θεόφιλος Μουρατίδης Jul 22 '16 at 11:40
28

Work with vectors is usually most effective to contact String.

I suggest the following function:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}

Run this snippet:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}

var str = "hello world";
str = str.replaceAt(3, "#");

document.write(str);

  • 8
    this is bad for large strings, no need to create an Array with crazy amount of cells if you can just use substr to cut it... – vsync Oct 24 '11 at 8:30
  • 1
    Useful if you need to change a lot of characters, and it is simple. – Sheepy Aug 22 '12 at 2:02
  • 6
    I created a test on jsperf: jsperf.com/replace-character-by-index -- Substr is way faster, and consistent from 32bytes up to 100kb. I upvoted this and as much as it hurts me to say, even though this feels nicer, substr is the better choice for strings of any size. – Cory Mawhorter May 9 '13 at 3:37
  • This is quite unoptimal. – Radko Dinev Aug 25 '14 at 7:09
  • This is a good quick solution if you know you are going to use small strings. If you are okay with extending the prototypes, then you could achieve similar behavior in 2 lines: Array.prototype.replace = function(index, val) { this[index] = val; return this; }; 'word'.split('').replace(1, '0').join(''); // returns 'w0rd' – Michael Plautz Mar 20 '18 at 15:04
25

In Javascript strings are immutable so you have to do something like

var x = "Hello world"
x = x.substring(0, i) + 'h' + x.substring(i+1);

To replace the character in x at i with 'h'

24
str = str.split('');
str[3] = 'h';
str = str.join('');
  • 3
    Clear and simple, but currently won't work with emoji (such as 😀) when using split and join – Green Jun 26 '16 at 10:15
  • 1
    With es6 I think that Array.from(str) might be a better option now, but I came here with that knowledge and learned something just as concise from you so thank you! – David Kamer Jun 23 '18 at 3:23
5

This method is good for small length strings but may be slow for larger text.

var x = "White Dog";
var arr = x.split(""); // ["W", "h", "i", "t", "e", " ", "D", "o", "g"]
arr.splice(6, 1, 'F');
var result = arr.join(""); // "White Fog"

/* 
  Here 6 is starting index and 1 is no. of array elements to remove and 
  final argument 'F' is the new character to be inserted. 
*/
4

This works similar to Array.splice:

String.prototype.splice = function (i, j, str) {
    return this.substr(0, i) + str + this.substr(j, this.length);
};
4

One-liner using String.replace with callback (no emoji support):

// 0 - index to replace, 'f' - replacement string
'dog'.replace(/./g, (c, i) => i == 0? 'f': c)
// "fog"

Explained:

//String.replace will call the callback on each pattern match
//in this case - each character
'dog'.replace(/./g, function (character, index) {
   if (index == 0) //we want to replace the first character
     return 'f'
   return character //leaving other characters the same
})
2

@CemKalyoncu: Thanks for the great answer!

I also adapted it slightly to make it more like the Array.splice method (and took @Ates' note into consideration):

spliceString=function(string, index, numToDelete, char) {
      return string.substr(0, index) + char + string.substr(index+numToDelete);
   }

var myString="hello world!";
spliceString(myString,myString.lastIndexOf('l'),2,'mhole'); // "hello wormhole!"
  • Not sure why this was voted down. It's a legit answer. It works as indicated. And it's consistent with Array.splice type functionality. – Scrimothy May 18 '15 at 14:40
1

I did a function that does something similar to what you ask, it checks if a character in string is in an array of not allowed characters if it is it replaces it with ''

    var validate = function(value){
        var notAllowed = [";","_",">","<","'","%","$","&","/","|",":","=","*"];
        for(var i=0; i<value.length; i++){
            if(notAllowed.indexOf(value.charAt(i)) > -1){
               value = value.replace(value.charAt(i), "");
               value = validate(value);
            }
       }
      return value;
   }
1

If you want to replace characters in string, you should create mutable strings. These are essentially character arrays. You could create a factory:

  function MutableString(str) {
    var result = str.split("");
    result.toString = function() {
      return this.join("");
    }
    return result;
  }

Then you can access the characters and the whole array converts to string when used as string:

  var x = MutableString("Hello");
  x[0] = "B"; // yes, we can alter the character
  x.push("!"); // good performance: no new string is created
  var y = "Hi, "+x; // converted to string: "Hi, Bello!"
1

I know this is old but the solution does not work for negative index so I add a patch to it. hope it helps someone

String.prototype.replaceAt=function(index, character) {
    if(index>-1) return this.substr(0, index) + character + this.substr(index+character.length);
    else return this.substr(0, this.length+index) + character + this.substr(index+character.length);

}
1

You could try

var strArr = str.split("");

strArr[0] = 'h';

str = strArr.join("");
0

You can extend the string type to include the inset method:

String.prototype.insert = function (index,value) {
  return this.substr(0, index) + value + this.substr(index,this.length);
};

var s = "new function";
alert(s.insert(4,"insert string "));

Then you can call the function:

0

Lets say you want to replace Kth index (0-based index) with 'Z'. You could use Regex to do this.

var re = var re = new RegExp("((.){" + K + "})((.){1})")
str.replace(re, "$1A$`");
  • Any idea why is this tagged not useful? – ksp Mar 17 '17 at 21:05
  • I haven't checked if this regex works, but maybe it's downvoted because it's probably a lot faster to create a new string, than compiling a state machine (regular expression), which is very expensive. – Felo Vilches Apr 8 '17 at 15:29
0

Here is a version I came up with if you want to style words or individual characters at their index.

replaceAt( yourArrayOfIndexes, yourString/orArrayOfStrings ) 

Working example: https://codesandbox.io/s/lr5zjxrn67

function replaceAt(indexArray, string) {
  let newString = [...string];

  for (let i = 0; i < indexArray.length; i++) {
    newString = Object.assign(newString, {
      [indexArray[i]]: <b>{newString[indexArray[i]]}</b>
    });
  }

  return newString;
}

And here is another alternate method

function replaceAt(indexArray, string) {
  const newString = [...string];

  return newString.map(i => {
    indexArray.map(i => {
      return (newString[i] = <b>{newString[i]}</b>);
    });
    return i;
  });
}
0

You can use the following function to replace Character or String at a particular position of a String. To replace all the following match cases use String.prototype.replaceAllMatches() function.

String.prototype.replaceMatch = function(matchkey, replaceStr, matchIndex) {
    var retStr = this, repeatedIndex = 0;
    for (var x = 0; (matchkey != null) && (retStr.indexOf(matchkey) > -1); x++) {
        if (repeatedIndex == 0 && x == 0) {
            repeatedIndex = retStr.indexOf(matchkey);
        } else { // matchIndex > 0
            repeatedIndex = retStr.indexOf(matchkey, repeatedIndex + 1);
        }
        if (x == matchIndex) {
            retStr = retStr.substring(0, repeatedIndex) + replaceStr + retStr.substring(repeatedIndex + (matchkey.length));
            matchkey = null; // To break the loop.
        }
    }
    return retStr;
};

Test:

var str = "yash yas $dfdas.**";

console.log('Index Matched replace : ', str.replaceMatch('as', '*', 2) );
console.log('Index Matched replace : ', str.replaceMatch('y', '~', 1) );

Output:

Index Matched replace :  yash yas $dfd*.**
Index Matched replace :  yash ~as $dfdas.**
-4

The methods on here are complicated. I would do it this way:

var myString = "this is my string";
myString = myString.replace(myString.charAt(number goes here), "insert replacement here");

This is as simple as it gets.

Not the answer you're looking for? Browse other questions tagged or ask your own question.