3372

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.

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
tags2k
  • 70,860
  • 30
  • 74
  • 105
  • 119
    Note that JQuery is a DOM and event manipulation library, not a language of its own. It has nothing to do with array manipulation. – Domino Feb 18 '15 at 15:36
  • 27
    https://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. – Tim Apr 14 '16 at 08:14
  • 6
    @Tim, But it's still not a language of its own (still there are some questions like "how to sum two numbers in jQuery" here on SO) – Victor May 07 '18 at 13:31
  • 5
    @Victor No, and never will be. jQuery was useful and relevant, but it's had its day. – Tim May 08 '18 at 06:17
  • 1
    Also, see **[this](https://stackoverflow.com/questions/51287428/how-does-the-spread-syntax-affect-array-splice/51287919)**, for a twisted surprise (: – noobie Oct 01 '18 at 05:48
  • I'm annoyed that the title of this question and its page title are different (jQuery vs. JS). Shows up differently in search results. – Andrew Jun 07 '20 at 00:14

20 Answers20

5503

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()); // Jani,Hege,Stale,Kai Jim,Borge
arr.splice(2, 0, "Lene");
console.log(arr.join()); // Jani,Hege,Lene,Stale,Kai Jim,Borge
etoxin
  • 3,828
  • 2
  • 31
  • 45
tvanfosson
  • 490,224
  • 93
  • 683
  • 780
  • 208
    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?! – tags2k Feb 25 '09 at 14:46
  • 96
    @tags2k: because the function does more than inserting items and it's name was already established in perl? – Christoph Feb 25 '09 at 14:53
  • 16
    doc: https://developer.mozilla.org/en/JavaScript/Guide/Predefined_Core_Objects#Array_Object – Dingo Mar 10 '11 at 09:54
  • 63
    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. – EBarr May 13 '14 at 01:45
  • 16
    I think the term "splice" makes sense. Splice means to join or connect, also to change. You have an established array that you are now "changing" which would involve adding or removing elements. You specify where in the array to start, then how many old items to remove (if any) and lastly, optionally a list of new elements to add. Splice is also a great sci-fi term of course. – Jakub Keller Nov 21 '14 at 15:45
  • 1
    Could someone please tell me from a performance point of view is using `splice` good in this case? I mean, if I have an array with thousands of items and I want to insert an element somewhere between two elements, how does JavaScript update the indexes of the array from that point where I insert the item to the end of the array? – tonix Oct 24 '15 at 20:56
  • @tonix I would think that it would be an O(n) operation as it has to shift all the values belonging to the indices following the items inserted. In the worst case (inserting an item at the beginning) that would be all of the (n) items in the array. – tvanfosson Oct 24 '15 at 22:17
  • I understand. Can it be improved somehow? I mean, I have just found something like `creating two separate indexes placed in the middle of the array` or `rotating arrays` but I didn't understand what the author of the article meant (https://gamealchemist.wordpress.com/2013/05/01/lets-get-those-javascript-arrays-to-work-fast/), point 6 at the end and 7 – tonix Oct 24 '15 at 22:23
  • I think he's talking about techniques to avoid resizing the array by keeping track of the the valid indices yourself. Unless you're facing a performance issue currently I wouldn't start trying to write your own array options. It'ls also possible that another data structure might work better - say balanced trees - depending on the need of your application. – tvanfosson Oct 24 '15 at 22:33
  • @tonix - Do you have an actual performance problem? If not, you're doing premature optimization, which leads to harder to maintain code with no benefit. Making splice perform well is the responsibility of the person writing the Javascript engine/library, not yours. Don't make it yours unless you have to (IE, your program is unacceptably slow unless you have some ugly hacks.) – ArtOfWarfare Jun 01 '16 at 02:36
  • @ArtOfWarfare As tvanfosson said, the amount of operations of splice is `O(n)`. Meanwhile, I have created a class which I call a `LinkedOrderedMap`, which allows me to insert items and keep them in order, and when I need to remove an item from the list I simply unlink the node where the item is located inside the list and tell the previous node that its next item now is the next node of the node I am going to remove. To insert an element between other elements in the list, I can use the same strategy, too. – tonix Jun 03 '16 at 06:57
  • @ArtOfWarfare Of course, I have to benchmark it before I can make assumptions about a performance gain, but with such an implementation the amount of required operations is constant. It doesn't matter how long the list is. I remember there was an online site where you can benchmark you JS code, but I couldn't remember the name. Could you pass me a link if you know it. I will then benchmark the code I have written against splice and tell what the results are. – tonix Jun 03 '16 at 06:59
  • @tonix - Your code is written in JavaScript and needs to be interpreted. Splice's code is likely more native. – ArtOfWarfare Jun 03 '16 at 12:19
  • @ArtOfWarfare Yes, I know. But I am curious to do a benchmark anyway. I just don't remember the name of the site where you benchmark JS code... – tonix Jun 04 '16 at 11:03
  • 2
    given that the new `class` and `constructor` elements for the new EMCAScript is nothing more than syntactic sugar for existing methods, would it be too much to make an `insert` function/alias ? – tetris11 Sep 23 '16 at 17:55
  • There should **definitely** be a syntactic sugar like *insert(what,where)* or *insertAt(what,where)*, preferably with *where* being set to the last index by default. – Konrad Viltersten Jan 25 '20 at 21:53
  • Splice was premature optimization, when JavaScript got "invented". Instead of just throwing in the common "insert/remove", they took the splice function, that does both and pains every newcomer. Now everybody is used to splice and will disagree with me. – Bitterblue Nov 02 '20 at 10:48
  • Splice removes elements(second parameter) at first, and then insert new elements(thrid and more parameters). Splice is very useful when you are going to work with your javascript array. –  Jan 12 '21 at 06:29
  • 16 years working as developer. Around ~12 years working with JS. And I still can't remember how to "push an item using an index". Just another fail for JS. – Broda Noel May 04 '21 at 18:24
  • Is there a certain critereria that you would you splice instead of just `array[index] = newValue`? – Nate Thompson May 13 '21 at 19:36
328

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' ]
K.Dᴀᴠɪs
  • 9,384
  • 11
  • 31
  • 39
FrEsC 81
  • 3,465
  • 1
  • 10
  • 2
  • 12
    To insert multiple items you can use `Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }` – Ryan Smith May 30 '14 at 12:15
  • 7
    The problem with adding stuff to array is that the function will show up as an element when you do for(i in arr) {...} – rep_movsd Jul 02 '14 at 09:38
  • 9
    But keep in mind that it's not recommended to extend native types since it might interfere with other code or future functionality. – marsze Aug 21 '18 at 09:48
  • 36
    Don’t modify objects you don’t own – Luis Cabrera Benito Feb 19 '19 at 18:09
  • 1
    @RyanSmith Or, with ES6, `Array.prototype.insert = function(index, ...items) { this.splice.call(this, index, 0, ...items); }`. – Solomon Ucko May 05 '19 at 02:39
  • 1
    @SolomonUcko yeah you could tbh for ES6 I'd just do `[...arr.slice(0, index), ...items, ...arr.slice(index)]` – Ryan Smith May 09 '19 at 20:13
  • @RyanSmith The problem is that that has to copy the start of the array, not just the end. – Solomon Ucko May 09 '19 at 20:14
  • 1
    @SolomonUcko that is true, if you're working with large arrays that is something to consider. For smaller arrays, I think that the benefits of immutability outweigh the negligible performance implications. Note that there is an answer here that uses this approach https://stackoverflow.com/a/38181008/1221906 so probably best to provide feedback there for people that are using this approach. – Ryan Smith May 11 '19 at 07:18
  • 8
    Don't modify prototypes – satya164 May 31 '19 at 12:54
178

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]
gafi
  • 9,663
  • 2
  • 27
  • 28
  • 2
    Is this a good, safe way to do this? I ask because this seems so elegant and concise but no other answers touch upon this. Most of them modify the prototype object! – anotherDev Dec 11 '17 at 09:32
  • 6
    @HarshKanchina That's probably because most of the answers are pre ES6, but this approach is very common now from my experience – gafi Dec 16 '17 at 22:35
  • This approach will always be slower and worse than splice. Don't be fooled by the pretty sugar syntax or the popularity among other misguided devs (\*cough\* gafi \*cough\*). Allocating a whole new array and discarding the old array is way slower than modifying the original array. If you need a copy, then call `slice()` before `splice()`. Never use the ES6 for such trivial things which can be done far better and far more cleanly with other APIs. – Jack Giffin Jan 19 '21 at 02:19
  • You should explain WHY you should avoid mutation. Is it slow? If so, how much slower? Is it worth the extra "hassle"? – Daniele Testa May 25 '21 at 09:34
79

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/

VisioN
  • 132,029
  • 27
  • 254
  • 262
  • Is there a compact way to have this version also merge an array when it finds one in the arguments? – Nolo Mar 30 '13 at 23:56
  • 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.) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice – Alexis Wilke Dec 12 '14 at 02:03
  • 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);` => `[ ]` – Alexis Wilke Dec 12 '14 at 02:08
  • @AlexisWilke In the first example I used [`slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/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? – VisioN Dec 12 '14 at 08:46
  • For some reason, when I go to use insert2, i get an "Expected 1 argument, but got 2" exception. – Corné Jun 26 '20 at 03:08
45

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);
Community
  • 1
  • 1
Luis Perez
  • 26,159
  • 10
  • 76
  • 77
  • 2
    Wouldn't insertAt() do better to call insertArrayAt() once it has created a single-element arrayToInsert? That avoids repetition of identical code. – Matt Sach Sep 10 '12 at 16:12
  • 1
    this is a great example of when to use 'apply' – CRice Jan 29 '15 at 00:44
  • 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)); – CRice Jan 29 '15 at 00:56
24

I recommend using pure JavaScript in this case, also there is no insert method in JavaScript, but we have a method which is a built-in Array method which does the job for you, it's called splice...

Let's see what's splice()...

The splice() method changes the contents of an array by removing existing elements and/or adding new elements.

OK, imagine we have this array below:

const arr = [1, 2, 3, 4, 5];

We can remove 3 like this:

arr.splice(arr.indexOf(3), 1);

It will return 3, but if we check the arr now, we have:

[1, 2, 4, 5]

So far, so good, but how we can add a new element to array using splice? Let's put back 3 in the arr...

arr.splice(2, 0, 3);

Let's see what we have done...

We use splice again, but this time for the second argument, we pass 0, means we want to delete no item, but at the same time, we add third argument which is 3 that will be added at second index...

You should be aware, that we can delete and add at the same time, for example now we can do:

arr.splice(2, 2, 3);

Which will delete 2 items at index 2, then add 3 at index 2 and result will be:

[1, 2, 3, 5];

This is showing how each item in splice work:

array.splice(start, deleteCount, item1, item2, item3 ...)

Alireza
  • 83,698
  • 19
  • 241
  • 152
  • 1
    Thanks for explaining in future i suggest using non digit numbers for the array values, for showing an example. Eg: arr.splice(2, 0, 3) vs arr.splice(2, 0, "C"). Easier for the reader to comprehend which argument maps to the value part and which one maps to the index part. Thank you! – Cristian E. Oct 09 '20 at 14:47
23

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));
Redu
  • 19,106
  • 4
  • 44
  • 59
  • 2
    "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`. – chrisbajorin May 22 '16 at 21:15
  • 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. – Redu May 22 '16 at 21:23
  • 1
    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) – NiKo Jun 02 '16 at 14:18
  • 1
    I think it is worth mentioning that the rest parameter is new ECMA 6th (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/rest_parameters ) – Geza Turi Dec 09 '16 at 17:02
18

Append Single Element at a specific index

//Append at specific position(here at index 1)
arrName.splice(1, 0,'newName1');
//1: index number, 0: number of element to remove, newName1: new element


//Append at specific position (here at index 3)
arrName[3] = 'newName1';

Append Multiple Element at a specific index

//Append from index number 1
arrName.splice(1, 0,'newElemenet1', 'newElemenet2', 'newElemenet3');
//1: index number from where append start, 
//0: number of element to remove, 
//newElemenet1,2,3: new elements
Ryan Taylor
  • 9,463
  • 2
  • 34
  • 31
Srikrushna
  • 2,652
  • 30
  • 37
  • 9
    Worth noticing that arrName[3] does not append, it overrides. – sfratini Sep 10 '18 at 22:40
  • It add the element to the existing array not over ride, Ex: let arrName = ['xxx', 'yyy', 'zzz']; arrName.splice(1, 0,'aaa', 'bbb', 'ccc'); after print the arrName – Srikrushna Sep 12 '18 at 18:49
  • If arrName has more than 3 elements you are overriding the 3rd, not appending. Or am I looking this at the wrong way? – sfratini Sep 12 '18 at 18:51
  • If we insert an element on the middle, it shift the next element not overide. Please specify your problem, what you need. Take an array(example) and what you need on the output. plz comment me – Srikrushna Sep 12 '18 at 18:56
  • I dont have a problem, what I am saying is that this does not append: arrName[3]. You are overriding whatever is in the 4th position. – sfratini Sep 12 '18 at 20:48
  • 2
    @Srikrushna `arrName[3] = 'newName1';` will append if the array has only 3 elements. If there is an element in index 3, this will be replaced. If you want to append at end, it is better to use `arrName.push('newName1');` – awe Nov 14 '19 at 08:24
  • @awe I am agree in your comment, but the question is in specific index, we have to insert the elements. For that question my answer is right – Srikrushna Dec 24 '20 at 06:16
15

Solutions & Performance

Today (2020.04.24) I perform tests for chosen solutions for big and small arrays . I tested them on MacOs High Sierra 10.13.6 on Chrome 81.0, Safari 13.1, Firefox 75.0.

Conclusions

For all browsers

  • surprisingly for small arrays non-in-place solutions based on slice and reduce (D,E,F) are usually 10x-100x faster than in-place solutions
  • for big arrays the in-place-solutions based on splice (AI,BI,CI) was fastest (sometimes ~100x - but it depends of array size)
  • for small arrays BI solution was slowest
  • for big arrays E solution was slowest

enter image description here

Details

Tests was divided into two groups: in-place solutions (AI,BI,CI) and non-in-place solutions (D,E,F) and was perform for two cases

  • test for array with 10 elements - you can run it HERE
  • test for array with 1.000.000 elements - you can run it HERE

Tested code is presented in below snippet

jsfiddle

function AI(arr, i, el) {
  arr.splice(i, 0, el);
  return arr;
}

function BI(arr, i, el) {
  Array.prototype.splice.apply(arr, [i, 0, el]);
  return arr;
}

function CI(arr, i, el) {
  Array.prototype.splice.call(arr, i, 0, el);
  return arr;
}

function D(arr, i, el) {
  return arr.slice(0, i).concat(el, arr.slice(i));
}

function E(arr, i, el) {
  return [...arr.slice(0, i), el, ...arr.slice(i)]
}

function F(arr, i, el) {
  return arr.reduce((s, a, j)=> (j-i ? s.push(a) : s.push(el, a), s), []);
}



// -------------
// TEST
// -------------

let arr = ["a", "b", "c", "d", "e", "f"];

let log = (n, f) => {
  let a = f([...arr], 3, "NEW");
  console.log(`${n}: [${a}]`);
};

log('AI', AI);
log('BI', BI);
log('CI', CI);
log('D', D);
log('E', E);
log('F', F);
This snippet only presents tested code (it not perform tests)

Example results for small array on chrome are below

enter image description here

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
  • 1
    The answer doesn't address the OP's question. – kabirbaidhya Sep 12 '20 at 05:52
  • 9
    @kabirbaidhya actually in this answer you can find many solutions to OP question, but additional value in this answer is performance comparison between them - I hope many people will find it useful – Kamil Kiełczewski Sep 12 '20 at 07:24
  • Perhaps, you may want to restructure your answer a bit so that it's intuitive for the users to see the possible solutions first and their performance implications later. It looks primarily focused on performance rn. – kabirbaidhya Sep 12 '20 at 07:46
12

Here are two ways :

const array = [ 'My', 'name', 'Hamza' ];

array.splice(2, 0, 'is');

console.log("Method 1 : ", array.join(" "));

OR

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

const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');

console.log("Method 2 : ", array.join(" "));
M. Hamza Rajput
  • 3,508
  • 1
  • 20
  • 20
10

Another possible solution, with usage of Array#reduce.

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

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

console.log(insert(arr, "banana", 1));
console.log(insert(arr2, 3, 2))
kind user
  • 32,209
  • 6
  • 49
  • 63
9

Array#splice() is the way to go, unless you really want to avoid mutating the array. Given 2 arrays arr1 and arr2, here's how you would insert the contents of arr2 into arr1 after the first element:

const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];

arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']

console.log(arr1)

If you are concerned about mutating the array (for example, if using Immutable.js), you can instead use slice(), not to be confused with splice() with a 'p'.

const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];
Community
  • 1
  • 1
vkarpov15
  • 2,465
  • 18
  • 17
7

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 positions, 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);
K.Dᴀᴠɪs
  • 9,384
  • 11
  • 31
  • 39
Ville
  • 3,657
  • 1
  • 32
  • 36
6

Anyone who's still having issues with this one and have tried all the options above and never got it. I'm sharing my solution, this is to take consideration that you don't wan't to explicitly state the properties of your object vs the array.

function isIdentical(left, right){
    return JSON.stringify(left) === JSON.stringify(right);
}

function contains(array, obj){
    let count = 0;
    array.map((cur) => {
          if(this.isIdentical(cur, obj)) count++;
    });
    return count > 0;
}

This is a combination of iterating the reference array and comparing it to the object you wanted to check, convert both of them into a string then iterated if it matched. Then you can just count. This can be improved but this is where I settled. Hope this helps.

Clyde
  • 672
  • 7
  • 17
5

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");
K.Dᴀᴠɪs
  • 9,384
  • 11
  • 31
  • 39
Pawan
  • 538
  • 1
  • 4
  • 18
  • 4
    simply copy pasted the answer above. this is not adding any value to the question. either you add a new answer or comment on existing. please try to contribute something new. we dont want to spoil this community – hannad rehman Oct 24 '17 at 06:50
5

Taking profit of reduce method as following:

function insert(arr, val, index) {
    return index >= arr.length 
        ? arr.concat(val)
        : arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}

So at this way we can return a new array (will be a cool functional way - more much better than use push or splice) with the element inserted at index, and if the index is greater than the length of the array it will be inserted at the end.

alejoko
  • 488
  • 5
  • 11
5

Immutable insertion

Using splice method is surely the best answer if you need to insert into an array in-place.

However, if you are looking for an immutable function that returns a new updated array instead of mutating the original array on insert, you can use the following function.

function insert(array, index) {
  const items = Array.prototype.slice.call(arguments, 2);

  return [].concat(array.slice(0, index), items, array.slice(index));
}

const list = ['one', 'two', 'three'];

const list1 = insert(list, 0, 'zero'); // Insert single item
const list2 = insert(list, 3, 'four', 'five', 'six'); // Insert multiple


console.log('Original list: ', list);
console.log('Inserted list1: ', list1);
console.log('Inserted list2: ', list2);

Note: This is a pre-ES2015 way of doing it so it works for both older and newer browsers.

If you're using ES6 then you can try out rest parameters too; see this answer.

kabirbaidhya
  • 2,581
  • 2
  • 29
  • 51
4

Here's a working function that I uses in one of my application.

This checks if item exit

let ifExist = (item, strings = [ '' ], position = 0) => {
     // output into an array with empty string. Important just in case their is no item. 
    let output = [ '' ];
    // check to see if the item that will be positioned exist.
    if (item) {
        // output should equal to array of strings. 
        output = strings;
       // use splice in order to break the array. 
       // use positition param to state where to put the item
       // and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position. 
        output.splice(position, 0, item);
    }
    //empty string is so we do not concatenate with comma or anything else. 
    return output.join("");
};

And then I call it below.

ifExist("friends", [ ' ( ', ' )' ], 1)}  // output: ( friends )
ifExist("friends", [ ' - '], 1)}  // output:  - friends 
ifExist("friends", [ ':'], 0)}  // output:   friends: 
Lesly Revenge
  • 706
  • 8
  • 14
4

A bit of an older thread, but I have to agree with Redu above because splice definitely has a bit of a confusing interface. And the response given by cdbajorin that "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" is, while accurate, proving the point. The function's intent is to splice or as said earlier by Jakob Keller, "to join or connect, also to change. You have an established array that you are now changing which would involve adding or removing elements...." Given that, the return value of the elements, if any, that were removed is awkward at best. And I 100% agree that this method could have been better suited to chaining if it had returned what seems natural, a new array with the spliced elements added. Then you could do things like ["19", "17"].splice(1,0,"18").join("...") or whatever you like with the returned array. The fact that it returns what was removed is just kinda nonsense IMHO. If the intention of the method was to "cut out a set of elements" and that was it's only intent, maybe. It seems like if I don't know what I'm cutting out already though, I probably have little reason to cut those elements out, doesn't it? It would be better if it behaved like concat, map, reduce, slice, etc where a new array is made from the existing array rather than mutating the existing array. Those are all chainable, and that IS a significant issue. It's rather common to chain array manipulation. Seems like the language needs to go one or the other direction and try to stick to it as much as possible. Javascript being functional and less declarative, it just seems like a strange deviation from the norm.

meem
  • 124
  • 1
  • 4
2

i like little safety and i use this

   Array.prototype.Insert = function (item, before) {
        if (!item) return;
        if (before == null || before < 0 || before > this.length - 1) {
            this.push(item);
            return;
        }
        this.splice(before, 0,item );
    }
    
    
   var t = ["a","b"]
   
   t.Insert("v",1)
    
    console.log(t )
hossein sedighian
  • 985
  • 1
  • 5
  • 12