322

I have two variables and need to insert string b into string a at the point represented by position. The result I'm looking for is "I want an apple". How can I do this with JavaScript?

var a = 'I want apple';
var b = ' an';
var position = 6;
John
  • 1
  • 13
  • 98
  • 177
sami
  • 7,515
  • 8
  • 33
  • 37

12 Answers12

467

var a = "I want apple";
var b = " an";
var position = 6;
var output = [a.slice(0, position), b, a.slice(position)].join('');
console.log(output);

Optional: As a prototype method of String

The following can be used to splice text within another string at a desired index, with an optional removeCount parameter.

if (String.prototype.splice === undefined) {
  /**
   * Splices text within a string.
   * @param {int} offset The position to insert the text at (before)
   * @param {string} text The text to insert
   * @param {int} [removeCount=0] An optional number of characters to overwrite
   * @returns {string} A modified string containing the spliced text.
   */
  String.prototype.splice = function(offset, text, removeCount=0) {
    let calculatedOffset = offset < 0 ? this.length + offset : offset;
    return this.substring(0, calculatedOffset) +
      text + this.substring(calculatedOffset + removeCount);
  };
}

let originalText = "I want apple";

// Positive offset
console.log(originalText.splice(6, " an"));
// Negative index
console.log(originalText.splice(-5, "an "));
// Chaining
console.log(originalText.splice(6, " an").splice(2, "need", 4).splice(0, "You", 1));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 3
    For long strings, this solution is faster (because it copies less) than nickf's solution. – pts Dec 06 '10 at 09:47
  • 39
    This solution is not faster. I was curious about this and ran a jsperf. This is a note to anyone who reads this in the future. http://jsperf.com/javascript-string-splice. Tested in latest FF/Chrome/IE10/IE9. I would use lean nickf's approach over this one for both clarity and performance. – junkyspace Aug 15 '13 at 19:47
  • 3
    Well, thats very possible. The answer here is almost 3 years old, the majority of browsers and versions back then, indeed performed way faster with an *Array* join (especially IE). – jAndy Aug 15 '13 at 21:03
  • 1
    I beg your pardon to have revived such an old question, but for what I'm worth it should be `var output = [a.slice(0, position + 1), b, a.slice(position)].join('');` to give the OPs "I want an apple", instead of "I wantan apple". – paulvs Dec 06 '13 at 18:12
  • 13
    @PaulVon Its never wrong to correct something, so no need to pardon. Anyway, I kind of disagree. The functionally does what its intended to do, insert a string at a certain position within another string. Actually the inserted string should be like " an", which would be more correct in this instance. – jAndy Dec 07 '13 at 02:33
  • With a one change you can make this solution the fastest: do not use the array conversion which is terribly slow. This makes it even 1% faster than nickf's solution. :) https://jsperf.com/javascript-string-splice-reloaded – wedi Jul 10 '18 at 08:45
  • I added a useful polyfill to the end of this response. – Mr. Polywhirl Feb 13 '20 at 19:56
323
var output = a.substring(0, position) + b + a.substring(position);

Edit: replaced .substr with .substring because .substr is now a legacy function (per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr)

froggomad
  • 1,747
  • 2
  • 17
  • 40
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 61
    According to @junkyspace https://jsperf.com/javascript-string-splice, this answer is **640x faster** than jAndy's one. – Paulo Coghi Nov 08 '16 at 02:13
  • 5
    `String.prototype.substr` is deprecated now. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr – Tivie Nov 01 '18 at 00:14
  • 2
    [`substring`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring) *in this case* is a direct replacement for the deprecated `substr`, so the answer becomes: `var output = a.substring(0, position) + b + a.substring(position);`. – Seafish May 02 '19 at 22:44
  • It's not strictly deprecated, but legacy, so a good idea to replace as it will likely become deprecated, and is recommended by MDN to use `.substring` – froggomad Jun 26 '19 at 11:33
42

You can add this function to string class

String.prototype.insert_at=function(index, string)
{   
  return this.substr(0, index) + string + this.substr(index);
}

so that you can use it on any string object:

var my_string = "abcd";
my_string.insertAt(1, "XX");
John
  • 1
  • 13
  • 98
  • 177
jasin_89
  • 1,993
  • 7
  • 30
  • 41
  • 6
    It is a bad practice to modify native object prototype: https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice – jhujhul Sep 15 '18 at 15:13
  • 1
    -1: doesn't modify original variable AND you incorrectly used `camelCase` instead of `underscore_case` in your second example –  Dec 28 '20 at 14:21
21

Using ES6 string literals, would be much shorter:

const insertAt = (str, sub, pos) => `${str.slice(0, pos)}${sub}${str.slice(pos)}`;
    
console.log(insertAt('I want apple', ' an', 6)) // logs 'I want an apple'
Izhaki
  • 23,372
  • 9
  • 69
  • 107
Stefan J
  • 1,587
  • 13
  • 17
10

Maybe it's even better if you determine position using indexOf() like this:

function insertString(a, b, at)
{
    var position = a.indexOf(at); 

    if (position !== -1)
    {
        return a.substr(0, position) + b + a.substr(position);    
    }  

    return "substring not found";
}

then call the function like this:

insertString("I want apple", "an ", "apple");

Note, that I put a space after the "an " in the function call, rather than in the return statement.

paulo62
  • 2,637
  • 1
  • 21
  • 15
  • 3
    This is not what it was asked. Even if this was the case this wouldn't work if you have multiple occurrences of the "at" substring – elachell Oct 25 '16 at 15:07
9

try

a.slice(0,position) + b + a.slice(position)

var a = "I want apple";
var b = " an";
var position = 6;

var r= a.slice(0,position) + b + a.slice(position);

console.log(r);

or regexp solution

"I want apple".replace(/^(.{6})/,"$1 an")

var a = "I want apple";
var b = " an";
var position = 6;

var r= a.replace(new RegExp(`^(.{${position}})`),"$1"+b);

console.log(r);
console.log("I want apple".replace(/^(.{6})/,"$1 an"));
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
6

The Underscore.String library has a function that does Insert

insert(string, index, substring) => string

like so

insert("I want apple", 6, " an");
// => "I want an apple"
wihlke
  • 2,455
  • 1
  • 19
  • 18
svarog
  • 9,477
  • 4
  • 61
  • 77
  • Not by me, but probably because there was no mention of that library in the question. But he also doesn't seem to exclude other libraries IMO.. – Dennis98 Oct 31 '18 at 13:10
  • 2
    Even though I dislike using libraries unless necessary, I upvoted to offset the downvote :P – froggomad Jun 26 '19 at 11:36
5

If ES2018's lookbehind is available, one more regexp solution, that makes use of it to "replace" at a zero-width position after the Nth character (similar to @Kamil Kiełczewski's, but without storing the initial characters in a capturing group):

"I want apple".replace(/(?<=^.{6})/, " an")

var a = "I want apple";
var b = " an";
var position = 6;

var r= a.replace(new RegExp(`(?<=^.{${position}})`), b);

console.log(r);
console.log("I want apple".replace(/(?<=^.{6})/, " an"));
dlauzon
  • 1,241
  • 16
  • 23
2
var array = a.split(' '); 
array.splice(position, 0, b);
var output = array.join(' ');

This would be slower, but will take care of the addition of space before and after the an Also, you'll have to change the value of position ( to 2, it's more intuitive now)

Ravindra Sane
  • 472
  • 3
  • 10
2

Quick fix! If you don't want to manually add a space, you can do this:

var a = "I want apple";
var b = "an";
var position = 6;
var output = [a.slice(0, position + 1), b, a.slice(position)].join('');
console.log(output);

(edit: i see that this is actually answered above, sorry!)

K. Yu
  • 21
  • 2
1

Well just a small change 'cause the above solution outputs

"I want anapple"

instead of

"I want an apple"

To get the output as

"I want an apple"

use the following modified code

var output = a.substr(0, position) + " " + b + a.substr(position);
pts
  • 80,836
  • 20
  • 110
  • 183
Clyde Lobo
  • 9,126
  • 7
  • 34
  • 61
  • 14
    yes, it's probably not desirable in *this* case, but adding an extra space automatically is almost definitely not desirable in *all* cases. – nickf Dec 06 '10 at 09:35
  • 14
    Wouldn't the correct solutions be to add the spaces in the string = ' an ', this way you can reuse the function – Tosh Jan 07 '13 at 10:35
1

With RegExp replace

var a = 'I want apple';
var b = ' an';
var position = 6;
var output = a.replace(new RegExp(`^(.{${position}})(.*)`), `$1${b}$2`);

console.log(output);

Info: