Questions How to insert an item into an array at a specific index?
tags2k Asked

I am looking for a Javascript array insert method, in the style of:

arr.insert(index, item)

Preferably in jQuery, but any Javascript implementation will do at this point.

Comments :

Note that JQuery is a DOM and event manipulation library, not a language of its own. It has nothing to do with array manipulation.

Tim replied

api.jquery.com/jQuery.inArray has nothing to do with the DOM or events. jQuery has evolved into a mixed toolkit for in browser JS development, leading to people expecting it to have a method for everything.

@Patrick Reddit is that → way

icc97 replied

If you just want to add an element at index 0 you can use unshift

kwarnke replied

With lodash you can use set: _.set(['a'], 2, 'c') => [ 'a', , 'c' ]


10 Answers :
tvanfosson answered

What you want is the splice function on the native array object.

arr.splice(index, 0, item); will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).

In this example we will create an array and add an element to it into index 2:

var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";

console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());

The output of the code above will be:

Jani,Hege,Stale,Kai Jim,Borge
Jani,Hege,Lene,Stale,Kai Jim,Borge
tags2k replied
Thanks, I thought I would feel stupid for asking but now that I know the answer I don't! Why on earth did they decide to call it splice when a more searchable term was in common use for the same function?!;
Christoph replied
@tags2k: because the function does more than inserting items and it's name was already established in perl?;
Claudiu replied
yesss... this makes much more sense than calling it insert... what a bizarre language JS ultimately is;
EBarr replied
Splice can insert, but just as frequently does not. For example: arr.splice(2,3) will remove 3 elements starting at index 2. Without passing the 3rd....Nth parameters nothing is inserted. So the name insert() doesn't do it justice either.;
Sami answered

You can implement the Array.insert method by doing this:

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

Then you can use it like:

var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');

// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
Capaj replied
Who owns Array? Ecma script comitee? I mean if you do it with Object.defineProperty it might not be as bad as Pavlo thinks it is.;
Ryan Smith replied
To insert multiple items you can use Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); };
rep_movsd replied
The problem with adding stuff to array is that the function will show up as an element when you do for(i in arr) {...};
What Pavlo is saying is that - if the native insert method is implemented, or 2 or more developers in your company will come with the same idea of creating insert for array object but implementation would be different... Well, you get the idea.;
VisioN answered

Custom array insert methods

1. With multiple arguments and chaining support

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    this.splice.apply(this, [index, 0].concat(
        Array.prototype.slice.call(arguments, 1)));
    return this;
};

It can insert multiple elements (as native splice does) and supports chaining:

["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]

2. With array-type arguments merging and chaining support

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    index = Math.min(index, this.length);
    arguments.length > 1
        && this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
        && this.insert.apply(this, arguments);
    return this;
};

It can merge arrays from the arguments with the given array and also supports chaining:

["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"

DEMO: http://jsfiddle.net/UPphH/

Nolo replied
Is there a compact way to have this version also merge an array when it finds one in the arguments?;
VisioN replied
@Nolo Yes, you can find it in the updated answer.;
Alexis Wilke replied
I don't understand the first result ["b", "X", "Y", "Z", "c"]. Why isn't "d" included? It seems to me that if you put 6 as the second parameter of slice() and there are 6 elements in the array starting from the specified index, then you should get all 6 elements in the return value. (The doc says howMany for that parameter.) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…;
Alexis Wilke replied
Actually, if I use an index of 3 or more, I get nothing in the output (case 1., FireFox) ["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3); => [ ];
VisioN replied
@AlexisWilke In the first example I used slice method and not splice, which you're referring to in the comment. Second parameter of slice (named end) is zero-based index at which to end extraction. slice extracts up to but not including end. Hence after insert you have ["a", "b", "X", "Y", "Z", "c", "d"], from which slice extracts elements with indices from 1 up to 6, i.e. from "b" to "d" but not including "d". Does it make sense?;
Gaafar answered

Other than splice, you can use this approach which will not mutate the original array, but will create a new array with the added item. You should usually avoid mutation whenever possible. I'm using ES6 spread operator here.

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, newItem) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted item
  newItem,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10)

console.log(result)
// [1, 10, 2, 3, 4, 5]

This can be used to add more than one item by tweaking the function a bit to use the rest operator for the new items, and spread that in the returned result as well

const items = [1, 2, 3, 4, 5]

const insert = (arr, index, ...newItems) => [
  // part of the array before the specified index
  ...arr.slice(0, index),
  // inserted items
  ...newItems,
  // part of the array after the specified index
  ...arr.slice(index)
]

const result = insert(items, 1, 10, 20)

console.log(result)
// [1, 10, 20, 2, 3, 4, 5]

Alex Alexeev replied
exactly the answer I was looking for. thank you!;
Community answered

If you want to insert multiple elements into an array at once check out this Stack Overflow answer: A better way to splice an array into an array in javascript

Also here are some functions to illustrate both examples:

function insertAt(array, index) {
    var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
    return insertArrayAt(array, index, arrayToInsert);
}

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
    return array;
}

Finally here is a jsFiddle so you can see it for youself: http://jsfiddle.net/luisperezphd/Wc8aS/

And this is how you use the functions:

// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");

// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);
Matt Sach replied
Wouldn't insertAt() do better to call insertArrayAt() once it has created a single-element arrayToInsert? That avoids repetition of identical code.;
CRice replied
this is a great example of when to use 'apply';
CRice replied
I added a removeCount parameter to this method to take advantages of splice's ability to also remove items at that index: Array.prototype.splice.apply(array, [index, removeCount || 0].concat(arrayToInsert));;
Redu answered

For proper functional programming and chaining purposes an invention of Array.prototype.insert() is essential. Actually splice could have been perfect if it had returned the mutated array instead of a totally meaningless empty array. So here it goes

Array.prototype.insert = function(i,...rest){
  this.splice(i,0,...rest)
  return this
}

var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");

Well ok the above with the Array.prototype.splice() one mutates the original array and some might complain like "you shouldn't modify what doesn't belong to you" and that might turn out to be right as well. So for the public welfare i would like to give another Array.prototype.insert() which doesn't mutate the original array. Here it goes;

Array.prototype.insert = function(i,...rest){
  return this.slice(0,i).concat(rest,this.slice(i));
}

var a = [3,4,8,9],
    b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));

cdbajorin replied
"a totally meaningless empty array" - it only returns an empty array when the second parameter is 0. If it's greater than 0, it returns the items removed from the array. Given that you're adding to a prototype, and splice mutates the original array, I don't think "proper functional programming" belongs anywhere in the vicinity of splice.;
Redu replied
We are talking about insert here and the second parameter of Array.prototype.splice() has to be zero. And what it returns have no meaning other than "i have not deleted anything" and since we use it for inserting an item we already have that information. If you don't want to mutate the original array then you can do the same with two Array.prototype.slice() and one Array.prototype.concat() operations. It's up to you.;
NiKo replied
Your second implementation is the cleanest from this whole page and you have zero votes. Please take mine and keep up the good work. (you should just avoid mutating the prototype but you already know that);
Geza Turi replied
I think it is worth mentioning that the rest parameter is new ECMA 6th (developer.mozilla.org/en/docs/Web/JavaScript/Reference/… );
hannad rehman answered

This:

var arr= ["India","China","Japan","USA"];

arr.splice(index, 0, item);

Will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).

Jacks replied
What if I wanted to push an item at index 9 for example ? I have tested it and, in your case, the item pushed will be at index 5. Any way to insert it at index 9 (and maybe fill the gap with null values for example ? I have a class of constants that keeps indexes and wanted to be sure that an item placed at a certain index can be retrieved with the same index, no matter the size of the array.;
hannad rehman replied
@Jacks thats a really interesting requirement. you can simply use this var arr= ["India","China","Japan","USA"]; arr[9]='hannad'; console.log(arr) will return array of lenth 10. all other elements at the unused indexes will be undefined;
Jacks replied
Thank you @hannad rehman, works perfectly !;
hannad rehman replied
@Jacks happy to help :);
Ville answered

Even though this has been answered already, I'm adding this note for an alternative approach..

I wanted to place a known number of items into an array, into specific postitions, as they come off of an "associative array" (i.e. an object) which by definition is not guaranteed to be in a sorted order. I wanted the resulting array to be an array of objects, but the objects to be in a specific order in the array since an array guarantees their order. So I did this..

First the source object, a JSONB string retrieved from PostgreSQL. I wanted to have it sorted by the "order" property in each child object.

var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';

var jsonb_obj = JSON.parse(jsonb_str);

Since the number of nodes in the object is known, I first create an array with the specified length:

var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);

And then iterate the object, placing the newly created temporary objects into the desired locations in the array without really any "sorting" taking place.

for (var key of Object.keys(jsonb_obj)) {
  var tobj = {};
  tobj[key] = jsonb_obj[key].abbr;

  var position = jsonb_obj[key].order - 1;
  sorted_array[position] = tobj;
}

console.dir(sorted_array);
yckart replied
Even, if the question is already answered, I like this idea!;
Kind user answered

Another possible solution, with usage of Array#reduce.

var arr = ["apple", "orange", "raspberry"],
    arr2 = [1, 2, 4];

function insert(arr, item, index) {
    arr = arr.reduce(function(s, a, i) {
      i == index ? s.push(item, a) : s.push(a);
      return s;
    }, []);   
    console.log(arr);
}

insert(arr, "banana", 1);
insert(arr2, 3, 2);

Pawan answered

I tried this and it is working fine!!!!

var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);

Index is the position where you want to insert or delete the element. 0 i.e the second parameters defines the number of element from the index to be removed item are the new entries which you want to make in array. It can be one or more than one.

initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");