Reputation: 84355
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.
Upvotes: 4320
Views: 3623889
Reputation: 18116
Using Array.prototype.splice()
is an elegant way of achieving it
const numbers = ['one', 'two', 'four', 'five']
numbers.splice(2, 0, 'three');
console.log(numbers)
Read more about Array.prototype.splice
Upvotes: 96
Reputation: 532615
You want 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
UPDATE (24 May 2024)
You can now use the toSpliced
method which behaves just like splice
, however it returns a new array without mutating the existing one.
You could update the previous example like so:
const updated = arr.toSpliced(2, 0, "Lene");
Upvotes: 6825
Reputation: 344
There's now the ToSpliced method.
const months = ["Jan", "Mar", "Apr", "May"];
// Inserting an element at index 1
const months2 = months.toSpliced(1, 0, "Feb");
Upvotes: 3
Reputation: 21
I'm late to the party, but here is a contribution to the effort, which allows for insertion of provided array into original array at a specific position, maintaining the size of the original array regardless of overflow in any direction. I didn't find this edge case in previous comments, so here we go.
Array.prototype.insertAt = function(pos, arr) {
// Inserts array <arr> at position <pos>
// pos can be negative in which case the inserted array is trimmed.
// Overflowing array elements will be trimmed so that the length of original array will always be retained.
if(pos<0) {
if(Math.abs(pos) > arr.length) {
return this
} else {
var del1 = arr.length - (arr.length + pos);
var partial = arr.slice(Math.abs(arr.length - (arr.length + pos)), arr.length);
this.splice(0, arr.length + pos);
this.unshift.apply(this, partial);
}
} else {
if(pos > this.length) {
return this;
}
var insertIndex = pos;
var insertLength = Math.min((this.length - insertIndex), arr.length);
var args = [insertIndex, insertLength].concat(arr.slice(0, insertLength));
Array.prototype.splice.apply(this, args);
}
}
Array.prototype.insertAt = function(pos, arr) {
// Inserts array <arr> at position <pos>
// pos can be negative in which case the arr end is trimmed.
// Overflowing array elements will be trimmed so that the length of original array will always be retained.
if(pos<0) {
if(Math.abs(pos) > arr.length) {
return this
} else {
var del1 = arr.length - (arr.length + pos);
var partial = arr.slice(Math.abs(arr.length - (arr.length + pos)), arr.length);
this.splice(0, arr.length + pos);
this.unshift.apply(this, partial);
}
} else {
if(pos > this.length) {
return this;
}
var insertIndex = pos;
var insertLength = Math.min((this.length - insertIndex), arr.length);
var args = [insertIndex, insertLength].concat(arr.slice(0, insertLength));
Array.prototype.splice.apply(this, args);
}
}
var b = [1,2,3,4,5];
var a = [0,0,0,0,0,0,0,0,0,0,0];
var numIterations = a.length + b.length;
for(var j= -b.length; j < numIterations; j++) {
var c = a.slice();
c.insertAt(j, b);
console.log("Position: " + j + ", result: [" + c.toString() + "]");
}
Upvotes: 0
Reputation: 4965
Append a single element at a specific index:
// Append at a 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 a specific position (here at index 3)
arrName[3] = 'newName1';
Append multiple elements 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
Upvotes: 23
Reputation: 10296
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(" "));
Upvotes: 23
Reputation: 31
//Suppose we have an array
let myArray = [2, 4, 6, 8, 10];
// Index where we want to insert the item
let indexToInsert = 3;
// Item we want to insert
let itemToInsert = 174;
// Now we Using splice() method to insert the item at the specified index
myArray.splice(indexToInsert, 0, itemToInsert);
// output with new value
console.log(myArray);
Upvotes: 2
Reputation: 662
const x = [3, 2, 6, 6, 2]
function addToIndex(arr, index, val){
let prevArr = arr.slice(0, index)
let nextArr = arr.slice(index)
return [...prevArr, val, ...nextArr]
}
console.log(addToIndex(x, 2, 'hello'))
Upvotes: 0
Reputation: 3296
Lots of answers but nobody mentions that splice
can't insert past the last element of the array.
const insertIntoArray = (array, index, ...values) => {
while (index > array.length) {
array.push(undefined);
}
array.splice(index, 0, ...values);
};
Upvotes: 0
Reputation: 50914
If you want to keep the original array untouched but return a new array with the element inserted into a particular index you can use the new .toSpliced()
method:
This avoids mutating the array in place:
// 0 1 2
const letters = ["A", "B", "D"];
const insertIndex = 2; // position in the array to insert
const correctLetters = letters.toSpliced(insertIndex, 0, "C"); // 0 means don't delete any items, just insert. "C" is the item you want to insert.
console.log(correctLetters); // ["A", "B", "C", "D"] (new array contains new char)
console.log(letters); // ["A", "B", "D"] (unmodified)
If you need to insert multiple items into the array, just like its sibling .splice()
, you can use .toSpliced()
with multiple arguments:
.toSpliced(insertIndex, 0, "C", "D", "E");
The above, for example, will insert "C"
, "D"
, and "E"
at insertIndex
into the array without modifying it, returning a new array instead.
Upvotes: 3
Reputation: 9394
splice()
for thatThe splice()
method usually receives three arguments when adding an element:
0
let array = ['item 1', 'item 2', 'item 3']
let insertAtIndex = 0
let itemsToRemove = 0
array.splice(insertAtIndex, itemsToRemove, 'insert this string at index 0')
console.log(array)
Upvotes: 47
Reputation: 4691
Multi purpose for ARRAY
and ARRAY OF OBJECT
reusable approach
let arr = [0,1,2];
let obj = [{ name: "abc"},{ name: "xyz"},{ name: "ijk"} ];
const addArrayItemAtIndex = ( array, index, newItem ) => {
return [...array.slice(0, index), newItem, ...array.slice(index)];
}
// For Array
console.log( addArrayItemAtIndex(arr, 2, 159 ) );
// For Array of Objects
console.log( addArrayItemAtIndex(obj, 0, { name: "AMOOS"} ) );
Upvotes: 1
Reputation: 919
You can do it with array.splice:
/**
* @param arr: Array
* @param item: item to insert
* @param index: index at which to insert
* @returns array with the inserted element
*/
export function _arrayInsertAt<T>(arr: T[], item: T, index: number) {
return arr.splice(index, 0, item);;
}
Upvotes: 6
Reputation: 4527
You can implement the Array.insert
method by doing this:
Array.prototype.insert = function ( index, ...items ) {
this.splice( index, 0, ...items );
};
Then you can use it like:
var arr = [ 'A', 'B', 'E' ];
arr.insert(2, 'C', 'D');
// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
Upvotes: 427
Reputation: 45
var array= [10,20,30,40]
var i;
var pos=2; //pos=index + 1
/*pos is position which we want to insert at which is index + 1.position two in an array is index 1.*/
var value=5
//value to insert
//Initialize from last array element
for(i=array.length-1;i>=pos-1;i--){
array[i+1]=array[i]
}
array[pos-1]=value
console.log(array)
Upvotes: 1
Reputation: 2063
I like a 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)
Upvotes: 5
Reputation: 12784
Other than splice, you can use this approach which will not mutate the original array, but it will create a new array with the added item. It is useful, when you need to avoid mutation. I'm using the 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]
Upvotes: 310
Reputation: 8319
Here's a simple function that supports inserting multiple values at the same time:
function add_items_to_array_at_position(array, index, new_items)
{
return [...array.slice(0, index), ...new_items, ...array.slice(index)];
}
Usage example:
let old_array = [1,2,5];
let new_array = add_items_to_array_at_position(old_array, 2, [3,4]);
console.log(new_array);
//Output: [1,2,3,4,5]
Upvotes: 1
Reputation: 2977
I do it like so:
const insert = (what, where, index) =>
([...where.slice(0, index), what , ...where.slice(index, where.length)]);
const insert = (what, where, index) =>
([...where.slice(0, index), what , ...where.slice(index, where.length)]);
const list = [1, 2, 3, 4, 5, 6];
const newList = insert('a', list, 2);
console.log(newList.indexOf('a') === 2);
Upvotes: 1
Reputation: 2760
Here is the modern (Typescript functional) way:
export const insertItemInList = <T>(
arr: T[],
index: number,
newItem: T
): T[] => [...arr.slice(0, index), newItem, ...arr.slice(index)]
Upvotes: 1
Reputation: 26191
For proper functional programming and chaining purposes, an invention of Array.prototype.insert()
is essential. Actually, the 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));
Upvotes: 40
Reputation: 28130
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 yourself: 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);
Upvotes: 56
Reputation: 3490
Using the 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-ES6 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.
Upvotes: 10
Reputation: 92627
Today (2020.04.24) I perform tests for chosen solutions for big and small arrays. I tested them on macOS v10.13.6 (High Sierra) on Chrome 81.0, Safari 13.1, and Firefox 75.0.
For all browsers
slice
and reduce
(D,E,F) are usually 10x-100x faster than in-place solutionssplice
(AI, BI, and CI) was fastest (sometimes ~100x - but it depends on the array size)Tests were divided into two groups: in-place solutions (AI, BI, and CI) and non-in-place solutions (D, E, and F) and was performed for two cases:
Tested code is presented in the below snippet:
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 a small array on Google Chrome are below:
Upvotes: 47
Reputation: 217
I have to agree with Redu's answer 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 kind of nonsense IMHO. If the intention of the method was to "cut out a set of elements" and that was its 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.
It 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.
Upvotes: 6
Reputation: 922
Here's a working function that I use in one of my applications.
This checks if an item exists:
let ifExist = (item, strings = [ '' ], position = 0) => {
// Output into an array with an empty string. Important just in case their isn't any item.
let output = [ '' ];
// Check to see if the item that will be positioned exist.
if (item) {
// Output should be equal to an array of strings.
output = strings;
// Use splice() in order to break the array.
// Use positional parameters 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:
Upvotes: 5
Reputation: 1120
Taking profit of the reduce method as follows:
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 in this way we can return a new array (will be a cool functional way - more much better than using 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.
Upvotes: 8
Reputation: 742
Anyone who's still having issues with this one and have tried all the options in previous answers and never got it. I'm sharing my solution, and this is to take into consideration that you don't want 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, converting both of them into a string, and then iterating if it matched. Then you can just count. This can be improved, but this is where I settled.
Upvotes: 8
Reputation: 104870
I recommend using pure JavaScript in this case. Also there isn't any 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, meaning we don't want to delete any item, but at the same time, we add a third argument which is the 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 two items at index 2. Then add 3 at index 2 and the result will be:
[1, 2, 3, 5];
This is showing how each item in splice work:
array.splice(start, deleteCount, item1, item2, item3 ...)
Upvotes: 33
Reputation: 41893
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))
Upvotes: 15