Move an array element from one array position to another - javascript

I'm having a hard time figuring out how to move an element of an array. For example, given the following:
var array = [ 'a', 'b', 'c', 'd', 'e'];
How can I write a function to move the element 'd' to the left of 'b' ?
Or 'a' to the right of 'c'?
After moving the elements, the indexes of the rest of the elements should be updated. The resulting array would be:
array = ['a', 'd', 'b', 'c', 'e']
This seems like it should be pretty simple, but I can't wrap my head around it.

If you'd like a version on npm, array-move is the closest to this answer, although it's not the same implementation. See its usage section for more details. The previous version of this answer (that modified Array.prototype.move) can be found on npm at array.prototype.move.
I had fairly good success with this function:
function array_move(arr, old_index, new_index) {
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing
};
// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1));
Note that the last return is simply for testing purposes: splice performs operations on the array in-place, so a return is not necessary. By extension, this move is an in-place operation. If you want to avoid that and return a copy, use slice.
Stepping through the code:
If new_index is greater than the length of the array, we want (I presume) to pad the array properly with new undefineds. This little snippet handles this by pushing undefined on the array until we have the proper length.
Then, in arr.splice(old_index, 1)[0], we splice out the old element. splice returns the element that was spliced out, but it's in an array. In our above example, this was [1]. So we take the first index of that array to get the raw 1 there.
Then we use splice to insert this element in the new_index's place. Since we padded the array above if new_index > arr.length, it will probably appear in the right place, unless they've done something strange like pass in a negative number.
A fancier version to account for negative indices:
function array_move(arr, old_index, new_index) {
while (old_index < 0) {
old_index += arr.length;
}
while (new_index < 0) {
new_index += arr.length;
}
if (new_index >= arr.length) {
var k = new_index - arr.length + 1;
while (k--) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing purposes
};
// returns [1, 3, 2]
console.log(array_move([1, 2, 3], -1, -2));
Which should account for things like array_move([1, 2, 3], -1, -2) properly (move the last element to the second to last place). Result for that should be [1, 3, 2].
Either way, in your original question, you would do array_move(arr, 0, 2) for a after c. For d before b, you would do array_move(arr, 3, 1).

I like this way. It's concise and it works.
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}
Note: always remember to check your array bounds.
Run Snippet in jsFiddle

Here's a one liner I found on JSPerf....
Array.prototype.move = function(from, to) {
this.splice(to, 0, this.splice(from, 1)[0]);
};
which is awesome to read, but if you want performance (in small data sets) try...
Array.prototype.move2 = function(pos1, pos2) {
// local variables
var i, tmp;
// cast input parameters to integers
pos1 = parseInt(pos1, 10);
pos2 = parseInt(pos2, 10);
// if positions are different and inside array
if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) {
// save element from position 1
tmp = this[pos1];
// move element down and shift other elements up
if (pos1 < pos2) {
for (i = pos1; i < pos2; i++) {
this[i] = this[i + 1];
}
}
// move element up and shift other elements down
else {
for (i = pos1; i > pos2; i--) {
this[i] = this[i - 1];
}
}
// put element from position 1 to destination
this[pos2] = tmp;
}
}
I can't take any credit, it should all go to Richard Scarrott. It beats the splice based method for smaller data sets in this performance test. It is however significantly slower on larger data sets as Darwayne points out.

The splice() method adds/removes items to/from an array, and returns the removed item(s).
Note: This method changes the original array. /w3schools/
Array.prototype.move = function(from,to){
this.splice(to,0,this.splice(from,1)[0]);
return this;
};
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(3,1);//["a", "d", "b", "c", "e"]
var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(0,2);//["b", "c", "a", "d", "e"]
as the function is chainable this works too:
alert(arr.move(0,2).join(','));
demo here

My 2c. Easy to read, it works, it's fast, it doesn't create new arrays.
function move(array, from, to) {
if( to === from ) return array;
var target = array[from];
var increment = to < from ? -1 : 1;
for(var k = from; k != to; k += increment){
array[k] = array[k + increment];
}
array[to] = target;
return array;
}

Here is my one liner ES6 solution with an optional parameter on.
if (typeof Array.prototype.move === "undefined") {
Array.prototype.move = function(from, to, on = 1) {
this.splice(to, 0, ...this.splice(from, on))
}
}
Adaptation of the first solution proposed by digiguru
The parameter on is the number of element starting from from you want to move.
Here is a chainable variation of this:
if (typeof Array.prototype.move === "undefined") {
Array.prototype.move = function(from, to, on = 1) {
return this.splice(to, 0, ...this.splice(from, on)), this
}
}
[3, 4, 5, 1, 2].move(3, 0, 2) // => [1, 2, 3, 4, 5]
If you'd like to avoid prototype pollution, here's a stand-alone function:
function move(array, from, to, on = 1) {
return array.splice(to, 0, ...array.splice(from, on)), array
}
move([3, 4, 5, 1, 2], 3, 0, 2) // => [1, 2, 3, 4, 5]
And finally, here's a pure function that doesn't mutate the original array:
function moved(array, from, to, on = 1) {
return array = array.slice(), array.splice(to, 0, ...array.splice(from, on)), array
}
This should cover basically every variation seen in every other answer.

Got this idea from #Reid of pushing something in the place of the item that is supposed to be moved to keep the array size constant. That does simplify calculations. Also, pushing an empty object has the added benefits of being able to search for it uniquely later on. This works because two objects are not equal until they are referring to the same object.
({}) == ({}); // false
So here's the function which takes in the source array, and the source, destination indexes. You could add it to the Array.prototype if needed.
function moveObjectAtIndex(array, sourceIndex, destIndex) {
var placeholder = {};
// remove the object from its initial position and
// plant the placeholder object in its place to
// keep the array length constant
var objectToMove = array.splice(sourceIndex, 1, placeholder)[0];
// place the object in the desired position
array.splice(destIndex, 0, objectToMove);
// take out the temporary object
array.splice(array.indexOf(placeholder), 1);
}

This is based on #Reid's solution. Except:
I'm not changing the Array prototype.
Moving an item out of bounds to the right does not create undefined items, it just moves the item to the right-most position.
Function:
function move(array, oldIndex, newIndex) {
if (newIndex >= array.length) {
newIndex = array.length - 1;
}
array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
return array;
}
Unit tests:
describe('ArrayHelper', function () {
it('Move right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 0, 1);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
})
it('Move left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 0);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the left', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, -2);
assert.equal(array[0], 2);
assert.equal(array[1], 1);
assert.equal(array[2], 3);
});
it('Move out of bounds to the right', function () {
let array = [1, 2, 3];
arrayHelper.move(array, 1, 4);
assert.equal(array[0], 1);
assert.equal(array[1], 3);
assert.equal(array[2], 2);
});
});

You can implement some basic calculus and create a universal function for moving array elements from one position to the other.
For JavaScript it looks like this:
function magicFunction (targetArray, indexFrom, indexTo) {
targetElement = targetArray[indexFrom];
magicIncrement = (indexTo - indexFrom) / Math.abs (indexTo - indexFrom);
for (Element = indexFrom; Element != indexTo; Element += magicIncrement){
targetArray[Element] = targetArray[Element + magicIncrement];
}
targetArray[indexTo] = targetElement;
}
Check out "moving array elements" at "Gloommatter" for detailed explanation.
https://web.archive.org/web/20121105042534/http://www.gloommatter.com:80/DDesign/programming/moving-any-array-elements-universal-function.html

I've implemented an immutable ECMAScript 6 solution based off of #Merc's answer over here:
const moveItemInArrayFromIndexToIndex = (array, fromIndex, toIndex) => {
if (fromIndex === toIndex) return array;
const newArray = [...array];
const target = newArray[fromIndex];
const inc = toIndex < fromIndex ? -1 : 1;
for (let i = fromIndex; i !== toIndex; i += inc) {
newArray[i] = newArray[i + inc];
}
newArray[toIndex] = target;
return newArray;
};
The variable names can be shortened, just used long ones so that the code can explain itself.

One approach would be to create a new array with the pieces in the order you want, using the slice method.
Example
var arr = [ 'a', 'b', 'c', 'd', 'e'];
var arr2 = arr.slice(0,1).concat( ['d'] ).concat( arr.slice(2,4) ).concat( arr.slice(4) );
arr.slice(0,1) gives you ['a']
arr.slice(2,4) gives you ['b', 'c']
arr.slice(4) gives you ['e']

Another pure JS variant using ES6 array spread operator with no mutation
const reorder = (array, sourceIndex, destinationIndex) => {
const smallerIndex = Math.min(sourceIndex, destinationIndex);
const largerIndex = Math.max(sourceIndex, destinationIndex);
return [
...array.slice(0, smallerIndex),
...(sourceIndex < destinationIndex
? array.slice(smallerIndex + 1, largerIndex + 1)
: []),
array[sourceIndex],
...(sourceIndex > destinationIndex
? array.slice(smallerIndex, largerIndex)
: []),
...array.slice(largerIndex + 1),
];
}
// returns ['a', 'c', 'd', 'e', 'b', 'f']
console.log(reorder(['a', 'b', 'c', 'd', 'e', 'f'], 1, 4))

The splice method of Array might help: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice
Just keep in mind it might be relatively expensive since it has to actively re-index the array.

I needed an immutable move method (one that didn't change the original array), so I adapted #Reid's accepted answer to simply use Object.assign to create a copy of the array before doing the splice.
Array.prototype.immutableMove = function (old_index, new_index) {
var copy = Object.assign([], this);
if (new_index >= copy.length) {
var k = new_index - copy.length;
while ((k--) + 1) {
copy.push(undefined);
}
}
copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
return copy;
};
Here is a jsfiddle showing it in action.

Array.prototype.moveUp = function (value, by) {
var index = this.indexOf(value),
newPos = index - (by || 1);
if (index === -1)
throw new Error("Element not found in array");
if (newPos < 0)
newPos = 0;
this.splice(index, 1);
this.splice(newPos, 0, value);
};
Array.prototype.moveDown = function (value, by) {
var index = this.indexOf(value),
newPos = index + (by || 1);
if (index === -1)
throw new Error("Element not found in array");
if (newPos >= this.length)
newPos = this.length;
this.splice(index, 1);
this.splice(newPos, 0, value);
};
var arr = ['banana', 'curyWurst', 'pc', 'remembaHaruMembaru'];
alert('withiout changes= '+arr[0]+' ||| '+arr[1]+' ||| '+arr[2]+' ||| '+arr[3]);
arr.moveDown(arr[2]);
alert('third word moved down= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);
arr.moveUp(arr[2]);
alert('third word moved up= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);
http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview

Here's one way to do it in an immutable way. It handles negative numbers as well as an added bonus. This is reduces number of possible bugs at the cost of performance compared to editing the original array.
const numbers = [1, 2, 3];
const moveElement = (array, from, to) => {
const copy = [...array];
const valueToMove = copy.splice(from, 1)[0];
copy.splice(to, 0, valueToMove);
return copy;
};
console.log(moveElement(numbers, 0, 2))
// > [2, 3, 1]
console.log(moveElement(numbers, -1, -3))
// > [3, 1, 2]

One approach would be to use splice() to remove the item from the array and then by using the splice() method once again, insert the removed item into the target index.
const array = ['a', 'b', 'c', 'd', 'e']
const newArray = moveItem(array, 3, 1) // move element from index 3 to index 1
function moveItem(arr, fromIndex, toIndex){
let itemRemoved = arr.splice(fromIndex, 1) // assign the removed item as an array
arr.splice(toIndex, 0, itemRemoved[0]) // insert itemRemoved into the target index
return arr
}
console.log(newArray)

In 2022, this typescript utility will work along with a unit test.
export const arrayMove = <T>(arr: T[], fromIndex: number, toIndex: number) => {
const newArr = [...arr];
newArr.splice(toIndex, 0, newArr.splice(fromIndex, 1)[0]);
return newArr;
};
const testArray = ['1', '2', '3', '4'];
describe('arrayMove', () => {
it('should move array item to toIndex', () => {
expect(arrayMove(testArray, 2, 0)).toEqual(['3', '1', '2', '4']);
expect(arrayMove(testArray, 3, 1)).toEqual(['1', '4', '2', '3']);
expect(arrayMove(testArray, 1, 2)).toEqual(['1', '3', '2', '4']);
expect(arrayMove(testArray, 0, 2)).toEqual(['2', '3', '1', '4']);
});
});

I love immutable, functional one liners :) ...
const swapIndex = (array, from, to) => (
from < to
? [...array.slice(0, from), ...array.slice(from + 1, to + 1), array[from], ...array.slice(to + 1)]
: [...array.slice(0, to), array[from], ...array.slice(to, from), ...array.slice(from + 1)]
);

Find and move an element from "n"th position to 0th position.
Eg: Find and move 'd' to 0th position:
let arr = [ 'a', 'b', 'c', 'd', 'e'];
arr = [...arr.filter(item => item === 'd'), ...arr.filter(item => item !== 'd')];

It is stated in many places (adding custom functions into Array.prototype) playing with the Array prototype could be a bad idea, anyway I combined the best from various posts, I came with this, using modern Javascript:
Object.defineProperty(Array.prototype, 'immutableMove', {
enumerable: false,
value: function (old_index, new_index) {
var copy = Object.assign([], this)
if (new_index >= copy.length) {
var k = new_index - copy.length;
while ((k--) + 1) { copy.push(undefined); }
}
copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
return copy
}
});
//how to use it
myArray=[0, 1, 2, 3, 4];
myArray=myArray.immutableMove(2, 4);
console.log(myArray);
//result: 0, 1, 3, 4, 2
Hope can be useful to anyone

This version isn't ideal for all purposes, and not everyone likes comma expressions, but here's a one-liner that's a pure expression, creating a fresh copy:
const move = (from, to, ...a) => (a.splice(to, 0, ...a.splice(from, 1)), a)
A slightly performance-improved version returns the input array if no move is needed, it's still OK for immutable use, as the array won't change, and it's still a pure expression:
const move = (from, to, ...a) =>
from === to
? a
: (a.splice(to, 0, ...a.splice(from, 1)), a)
The invocation of either is
const shuffled = move(fromIndex, toIndex, ...list)
i.e. it relies on spreading to generate a fresh copy. Using a fixed arity 3 move would jeopardize either the single expression property, or the non-destructive nature, or the performance benefit of splice. Again, it's more of an example that meets some criteria than a suggestion for production use.

const move = (from, to, ...a) =>from === to ? a : (a.splice(to, 0, ...a.splice(from, 1)), a);
const moved = move(0, 2, ...['a', 'b', 'c']);
console.log(moved)

I thought this was a swap problem but it's not. Here's my one-liner solution:
const move = (arr, from, to) => arr.map((item, i) => i === to ? arr[from] : (i >= Math.min(from, to) && i <= Math.max(from, to) ? arr[i + Math.sign(to - from)] : item));
Here's a small test:
let test = ['a', 'b', 'c', 'd', 'e'];
console.log(move(test, 0, 2)); // [ 'b', 'c', 'a', 'd', 'e' ]
console.log(move(test, 1, 3)); // [ 'a', 'c', 'd', 'b', 'e' ]
console.log(move(test, 2, 4)); // [ 'a', 'b', 'd', 'e', 'c' ]
console.log(move(test, 2, 0)); // [ 'c', 'a', 'b', 'd', 'e' ]
console.log(move(test, 3, 1)); // [ 'a', 'd', 'b', 'c', 'e' ]
console.log(move(test, 4, 2)); // [ 'a', 'b', 'e', 'c', 'd' ]
console.log(move(test, 4, 0)); // [ 'e', 'a', 'b', 'c', 'd' ]

This is a really simple method using splice
Array.prototype.moveToStart = function(index) {
this.splice(0, 0, this.splice(index, 1)[0]);
return this;
};

I ended up combining two of these to work a little better when moving both small and large distances. I get fairly consistent results, but this could probably be tweaked a little bit by someone smarter than me to work differently for different sizes, etc.
Using some of the other methods when moving objects small distances was significantly faster (x10) than using splice. This might change depending on the array lengths though, but it is true for large arrays.
function ArrayMove(array, from, to) {
if ( Math.abs(from - to) > 60) {
array.splice(to, 0, array.splice(from, 1)[0]);
} else {
// works better when we are not moving things very far
var target = array[from];
var inc = (to - from) / Math.abs(to - from);
var current = from;
for (; current != to; current += inc) {
array[current] = array[current + inc];
}
array[to] = target;
}
}
https://web.archive.org/web/20181026015711/https://jsperf.com/arraymove-many-sizes

TypeScript Version
Copied from #Merc's answer. I like that one best because it is not creating new arrays and modifies the array in place. All I did was update to ES6 and add the types.
export function moveItemInArray<T>(workArray: T[], fromIndex: number, toIndex: number): T[] {
if (toIndex === fromIndex) {
return workArray;
}
const target = workArray[fromIndex];
const increment = toIndex < fromIndex ? -1 : 1;
for (let k = fromIndex; k !== toIndex; k += increment) {
workArray[k] = workArray[k + increment];
}
workArray[toIndex] = target;
return workArray;
}

Array.move.js
Summary
Moves elements within an array, returning an array containing the moved elements.
Syntax
array.move(index, howMany, toIndex);
Parameters
index: Index at which to move elements. If negative, index will start from the end.
howMany: Number of elements to move from index.
toIndex: Index of the array at which to place the moved elements. If negative, toIndex will start from the end.
Usage
array = ["a", "b", "c", "d", "e", "f", "g"];
array.move(3, 2, 1); // returns ["d","e"]
array; // returns ["a", "d", "e", "b", "c", "f", "g"]
Polyfill
Array.prototype.move || Object.defineProperty(Array.prototype, "move", {
value: function (index, howMany, toIndex) {
var
array = this,
index = parseInt(index) || 0,
index = index < 0 ? array.length + index : index,
toIndex = parseInt(toIndex) || 0,
toIndex = toIndex < 0 ? array.length + toIndex : toIndex,
toIndex = toIndex <= index ? toIndex : toIndex <= index + howMany ? index : toIndex - howMany,
moved;
array.splice.apply(array, [toIndex, 0].concat(moved = array.splice(index, howMany)));
return moved;
}
});

I used the nice answer of #Reid, but struggled with moving an element from the end of an array one step further - to the beginning (like in a loop).
E.g. ['a', 'b', 'c'] should become ['c', 'a', 'b'] by calling .move(2,3)
I achieved this by changing the case for new_index >= this.length.
Array.prototype.move = function (old_index, new_index) {
console.log(old_index + " " + new_index);
while (old_index < 0) {
old_index += this.length;
}
while (new_index < 0) {
new_index += this.length;
}
if (new_index >= this.length) {
new_index = new_index % this.length;
}
this.splice(new_index, 0, this.splice(old_index, 1)[0]);
return this; // for testing purposes
};

As an addition to Reid's excellent answer (and because I cannot comment);
You can use modulo to make both negative indices and too large indices "roll over":
function array_move(arr, old_index, new_index) {
new_index =((new_index % arr.length) + arr.length) % arr.length;
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr; // for testing
}
// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1));

Related

efficient way to remove an object from an array of objects [duplicate]

How do I remove a specific value from an array? Something like:
array.remove(value);
Constraints: I have to use core JavaScript. Frameworks are not allowed.
Find the index of the array element you want to remove using indexOf, and then remove that index with splice.
The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.
const array = [2, 5, 9];
console.log(array);
const index = array.indexOf(5);
if (index > -1) { // only splice array when item is found
array.splice(index, 1); // 2nd parameter means remove one item only
}
// array = [2, 9]
console.log(array);
The second parameter of splice is the number of elements to remove. Note that splice modifies the array in place and returns a new array containing the elements that have been removed.
For the reason of completeness, here are functions. The first function removes only a single occurrence (i.e. removing the first match of 5 from [2,5,9,1,5,8,5]), while the second function removes all occurrences:
function removeItemOnce(arr, value) {
var index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
function removeItemAll(arr, value) {
var i = 0;
while (i < arr.length) {
if (arr[i] === value) {
arr.splice(i, 1);
} else {
++i;
}
}
return arr;
}
// Usage
console.log(removeItemOnce([2,5,9,1,5,8,5], 5))
console.log(removeItemAll([2,5,9,1,5,8,5], 5))
In TypeScript, these functions can stay type-safe with a type parameter:
function removeItem<T>(arr: Array<T>, value: T): Array<T> {
const index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
Edited on 2016 October
Do it simple, intuitive and explicit (Occam's razor)
Do it immutable (original array stays unchanged)
Do it with standard JavaScript functions, if your browser doesn't support them - use polyfill
In this code example I use array.filter(...) function to remove unwanted items from an array. This function doesn't change the original array and creates a new one. If your browser doesn't support this function (e.g. Internet Explorer before version 9, or Firefox before version 1.5), consider polyfilling with core-js.
Removing item (ECMA-262 Edition 5 code AKA old style JavaScript)
var value = 3
var arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(function(item) {
return item !== value
})
console.log(arr)
// [ 1, 2, 4, 5 ]
Removing item (ECMAScript 6 code)
let value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
IMPORTANT ECMAScript 6 () => {} arrow function syntax is not supported in Internet Explorer at all, Chrome before version 45, Firefox before version 22, and Safari before version 10. To use ECMAScript 6 syntax in old browsers you can use BabelJS.
Removing multiple items (ECMAScript 7 code)
An additional advantage of this method is that you can remove multiple items
let forDeletion = [2, 3, 5]
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!
console.log(arr)
// [ 1, 4 ]
IMPORTANT array.includes(...) function is not supported in Internet Explorer at all, Chrome before version 47, Firefox before version 43, Safari before version 9, and Edge before version 14 but you can polyfill with core-js.
Removing multiple items (in the future, maybe)
If the "This-Binding Syntax" proposal is ever accepted, you'll be able to do this:
// array-lib.js
export function remove(...forDeletion) {
return this.filter(item => !forDeletion.includes(item))
}
// main.js
import { remove } from './array-lib.js'
let arr = [1, 2, 3, 4, 5, 3]
// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)
console.log(arr)
// [ 1, 4 ]
Try it yourself in BabelJS :)
Reference
Array.prototype.includes
Functional composition
I don't know how you are expecting array.remove(int) to behave. There are three possibilities I can think of that you might want.
To remove an element of an array at an index i:
array.splice(i, 1);
If you want to remove every element with value number from the array:
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] === number) {
array.splice(i, 1);
}
}
If you just want to make the element at index i no longer exist, but you don't want the indexes of the other elements to change:
delete array[i];
It depends on whether you want to keep an empty spot or not.
If you do want an empty slot:
array[index] = undefined;
If you don't want an empty slot:
//To keep the original:
//oldArray = [...array];
//This modifies the array.
array.splice(index, 1);
And if you need the value of that item, you can just store the returned array's element:
var value = array.splice(index, 1)[0];
If you want to remove at either end of the array, you can use array.pop() for the last one or array.shift() for the first one (both return the value of the item as well).
If you don't know the index of the item, you can use array.indexOf(item) to get it (in a if() to get one item or in a while() to get all of them). array.indexOf(item) returns either the index or -1 if not found.
A friend was having issues in Internet Explorer 8 and showed me what he did. I told him it was wrong, and he told me he got the answer here. The current top answer will not work in all browsers (Internet Explorer 8 for example), and it will only remove the first occurrence of the item.
Remove ALL instances from an array
function removeAllInstances(arr, item) {
for (var i = arr.length; i--;) {
if (arr[i] === item) arr.splice(i, 1);
}
}
It loops through the array backwards (since indices and length will change as items are removed) and removes the item if it's found. It works in all browsers.
There are two major approaches
splice(): anArray.splice(index, 1);
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = fruits.splice(2, 1);
// fruits is ['Apple', 'Banana', 'Orange']
// removed is ['Mango']
delete: delete anArray[index];
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = delete fruits(2);
// fruits is ['Apple', 'Banana', undefined, 'Orange']
// removed is true
Be careful when you use the delete for an array. It is good for deleting attributes of objects, but not so good for arrays. It is better to use splice for arrays.
Keep in mind that when you use delete for an array you could get wrong results for anArray.length. In other words, delete would remove the element, but it wouldn't update the value of the length property.
You can also expect to have holes in index numbers after using delete, e.g. you could end up with having indexes 1, 3, 4, 8, 9, and 11 and length as it was before using delete. In that case, all indexed for loops would crash, since indexes are no longer sequential.
If you are forced to use delete for some reason, then you should use for each loops when you need to loop through arrays. As the matter of fact, always avoid using indexed for loops, if possible. That way the code would be more robust and less prone to problems with indexes.
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
var fruits = ['apple', 'banana', 'carrot', 'orange'];
fruits.removeByValue('banana');
console.log(fruits);
// -> ['apple', 'carrot', 'orange']
There isn't any need to use indexOf or splice. However, it performs better if you only want to remove one occurrence of an element.
Find and move (move):
function move(arr, val) {
var j = 0;
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i] !== val) {
arr[j++] = arr[i];
}
}
arr.length = j;
}
Use indexOf and splice (indexof):
function indexof(arr, val) {
var i;
while ((i = arr.indexOf(val)) != -1) {
arr.splice(i, 1);
}
}
Use only splice (splice):
function splice(arr, val) {
for (var i = arr.length; i--;) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
Run-times on Node.js for an array with 1000 elements (averaged over 10,000 runs):
indexof is approximately 10 times slower than move. Even if improved by removing the call to indexOf in splice, it performs much worse than move.
Remove all occurrences:
move 0.0048 ms
indexof 0.0463 ms
splice 0.0359 ms
Remove first occurrence:
move_one 0.0041 ms
indexof_one 0.0021 ms
This provides a predicate instead of a value.
NOTE: it will update the given array, and return the affected rows.
Usage
var removed = helper.remove(arr, row => row.id === 5 );
var removed = helper.removeAll(arr, row => row.name.startsWith('BMW'));
Definition
var helper = {
// Remove and return the first occurrence
remove: function(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) {
return array.splice(i, 1);
}
}
},
// Remove and return all occurrences
removeAll: function(array, predicate) {
var removed = [];
for (var i = 0; i < array.length; ) {
if (predicate(array[i])) {
removed.push(array.splice(i, 1));
continue;
}
i++;
}
return removed;
},
};
You can do it easily with the filter method:
function remove(arrOriginal, elementToRemove){
return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));
This removes all elements from the array and also works faster than a combination of slice and indexOf.
Using filter is an elegant way to achieve this requirement.
filter will not mutate the original array.
const num = 3;
let arr = [1, 2, 3, 4];
const arr2 = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 4]
You can use filter and then assign the result to the original array if you want to achieve a mutation removal behaviour.
const num = 3;
let arr = [1, 2, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
By the way, filter will remove all of the occurrences matched in the condition (not just the first occurrence) like you can see in the following example
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
In case, you just want to remove the first occurrence, you can use the splice method
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
const idx = arr.indexOf(num);
arr.splice(idx, idx !== -1 ? 1 : 0);
console.log(arr); // [1, 2, 3, 3, 4]
John Resig posted a good implementation:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
If you don’t want to extend a global object, you can do something like the following, instead:
// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
var rest = array.slice((to || from) + 1 || array.length);
array.length = from < 0 ? array.length + from : from;
return array.push.apply(array, rest);
};
But the main reason I am posting this is to warn users against the alternative implementation suggested in the comments on that page (Dec 14, 2007):
Array.prototype.remove = function(from, to) {
this.splice(from, (to=[0, from || 1, ++to - from][arguments.length]) < 0 ? this.length + to : to);
return this.length;
};
It seems to work well at first, but through a painful process I discovered it fails when trying to remove the second to last element in an array. For example, if you have a 10-element array and you try to remove the 9th element with this:
myArray.remove(8);
You end up with an 8-element array. I don't know why, but I confirmed John's original implementation doesn't have this problem.
You can use ES6. For example to delete the value '3' in this case:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);
Output :
["1", "2", "4", "5", "6"]
Underscore.js can be used to solve issues with multiple browsers. It uses in-build browser methods if present. If they are absent like in the case of older Internet Explorer versions it uses its own custom methods.
A simple example to remove elements from array (from the website):
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
If you want a new array with the deleted positions removed, you can always delete the specific element and filter out the array. It might need an extension of the array object for browsers that don't implement the filter method, but in the long term it's easier since all you do is this:
var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));
It should display [1, 2, 3, 4, 6].
Here are a few ways to remove an item from an array using JavaScript.
All the method described do not mutate the original array, and instead create a new one.
If you know the index of an item
Suppose you have an array, and you want to remove an item in position i.
One method is to use slice():
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))
console.log(filteredItems)
slice() creates a new array with the indexes it receives. We simply create a new array, from start to the index we want to remove, and concatenate another array from the first position following the one we removed to the end of the array.
If you know the value
In this case, one good option is to use filter(), which offers a more declarative approach:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)
console.log(filteredItems)
This uses the ES6 arrow functions. You can use the traditional functions to support older browsers:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
return item !== valueToRemove
})
console.log(filteredItems)
or you can use Babel and transpile the ES6 code back to ES5 to make it more digestible to old browsers, yet write modern JavaScript in your code.
Removing multiple items
What if instead of a single item, you want to remove many items?
Let's find the simplest solution.
By index
You can just create a function and remove items in series:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const removeItem = (items, i) =>
items.slice(0, i-1).concat(items.slice(i, items.length))
let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]
console.log(filteredItems)
By value
You can search for inclusion inside the callback function:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]
console.log(filteredItems)
Avoid mutating the original array
splice() (not to be confused with slice()) mutates the original array, and should be avoided.
(originally posted on my site https://flaviocopes.com/how-to-remove-item-from-array/)
Check out this code. It works in every major browser.
remove_item = function(arr, value) {
var b = '';
for (b in arr) {
if (arr[b] === value) {
arr.splice(b, 1);
break;
}
}
return arr;
};
var array = [1,3,5,6,5,9,5,3,55]
var res = remove_item(array,5);
console.log(res)
Removing a particular element/string from an array can be done in a one-liner:
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
where:
theArray: the array you want to remove something particular from
stringToRemoveFromArray: the string you want to be removed and 1 is the number of elements you want to remove.
NOTE: If "stringToRemoveFromArray" is not located in the array, this will remove the last element of the array.
It's always good practice to check if the element exists in your array first, before removing it.
if (theArray.indexOf("stringToRemoveFromArray") >= 0){
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}
Depending if you have newer or older version of Ecmascript running on your client's computers:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
OR
var array = ['1','2','3','4','5','6'];
var newArray = array.filter(function(item){ return item !== '3' });
Where '3' is the value you want to be removed from the array.
The array would then become : ['1','2','4','5','6']
ES10
This post summarizes common approaches to element removal from an array as of ECMAScript 2019 (ES10).
1. General cases
1.1. Removing Array element by value using .splice()
| In-place: Yes |
| Removes duplicates: Yes(loop), No(indexOf) |
| By value / index: By index |
If you know the value you want to remove from an array you can use the splice method. First, you must identify the index of the target item. You then use the index as the start element and remove just one element.
// With a 'for' loop
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
for( let i = 0; i < arr.length; i++){
if ( arr[i] === 5) {
arr.splice(i, 1);
}
} // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
// With the .indexOf() method
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
const i = arr.indexOf(5);
arr.splice(i, 1); // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
1.2. Removing Array element using the .filter() method
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
The specific element can be filtered out from the array, by providing a filtering function. Such function is then called for every element in the array.
const value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
1.3. Removing Array element by extending Array.prototype
| In-place: Yes/No (Depends on implementation) |
| Removes duplicates: Yes/No (Depends on implementation) |
| By value / index: By index / By value (Depends on implementation) |
The prototype of Array can be extended with additional methods. Such methods will be then available to use on created arrays.
Note: Extending prototypes of objects from the standard library of JavaScript (like Array) is considered by some as an antipattern.
// In-place, removes all, by value implementation
Array.prototype.remove = function(item) {
for (let i = 0; i < this.length; i++) {
if (this[i] === item) {
this.splice(i, 1);
}
}
}
const arr1 = [1,2,3,1];
arr1.remove(1) // arr1 equals [2,3]
// Non-stationary, removes first, by value implementation
Array.prototype.remove = function(item) {
const arr = this.slice();
for (let i = 0; i < this.length; i++) {
if (arr[i] === item) {
arr.splice(i, 1);
return arr;
}
}
return arr;
}
let arr2 = [1,2,3,1];
arr2 = arr2.remove(1) // arr2 equals [2,3,1]
1.4. Removing Array element using the delete operator
| In-place: Yes |
| Removes duplicates: No |
| By value / index: By index |
Using the delete operator does not affect the length property. Nor does it affect the indexes of subsequent elements. The array becomes sparse, which is a fancy way of saying the deleted item is not removed but becomes undefined.
const arr = [1, 2, 3, 4, 5, 6];
delete arr[4]; // Delete element with index 4
console.log( arr ); // [1, 2, 3, 4, undefined, 6]
The delete operator is designed to remove properties from JavaScript objects, which arrays are objects.
1.5. Removing Array element using Object utilities (>= ES10)
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
ES10 introduced Object.fromEntries, which can be used to create the desired Array from any Array-like object and filter unwanted elements during the process.
const object = [1,2,3,4];
const valueToRemove = 3;
const arr = Object.values(Object.fromEntries(
Object.entries(object)
.filter(([ key, val ]) => val !== valueToRemove)
));
console.log(arr); // [1,2,4]
2. Special cases
2.1 Removing element if it's at the end of the Array
2.1.1. Changing Array length
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
JavaScript Array elements can be removed from the end of an array by setting the length property to a value less than the current value. Any element whose index is greater than or equal to the new length will be removed.
const arr = [1, 2, 3, 4, 5, 6];
arr.length = 5; // Set length to remove element
console.log( arr ); // [1, 2, 3, 4, 5]
2.1.2. Using .pop() method
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The pop method removes the last element of the array, returns that element, and updates the length property. The pop method modifies the array on which it is invoked, This means unlike using delete the last element is removed completely and the array length reduced.
const arr = [1, 2, 3, 4, 5, 6];
arr.pop(); // returns 6
console.log( arr ); // [1, 2, 3, 4, 5]
2.2. Removing element if it's at the beginning of the Array
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The .shift() method works much like the pop method except it removes the first element of a JavaScript array instead of the last. When the element is removed the remaining elements are shifted down.
const arr = [1, 2, 3, 4];
arr.shift(); // returns 1
console.log( arr ); // [2, 3, 4]
2.3. Removing element if it's the only element in the Array
| In-place: Yes |
| Removes duplicates: N/A |
| By value / index: N/A |
The fastest technique is to set an array variable to an empty array.
let arr = [1];
arr = []; //empty array
Alternatively technique from 2.1.1 can be used by setting length to 0.
You can use lodash _.pull (mutate array), _.pullAt (mutate array) or _.without (does't mutate array),
var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']
var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']
var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']
ES6 & without mutation: (October 2016)
const removeByIndex = (list, index) =>
[
...list.slice(0, index),
...list.slice(index + 1)
];
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
console.log(output)
Performance
Today (2019-12-09) I conduct performance tests on macOS v10.13.6 (High Sierra) for chosen solutions. I show delete (A), but I do not use it in comparison with other methods, because it left empty space in the array.
The conclusions
the fastest solution is array.splice (C) (except Safari for small arrays where it has the second time)
for big arrays, array.slice+splice (H) is the fastest immutable solution for Firefox and Safari; Array.from (B) is fastest in Chrome
mutable solutions are usually 1.5x-6x faster than immutable
for small tables on Safari, surprisingly the mutable solution (C) is slower than the immutable solution (G)
Details
In tests, I remove the middle element from the array in different ways. The A, C solutions are in-place. The B, D, E, F, G, H solutions are immutable.
Results for an array with 10 elements
In Chrome the array.splice (C) is the fastest in-place solution. The array.filter (D) is the fastest immutable solution. The slowest is array.slice (F). You can perform the test on your machine here.
Results for an array with 1.000.000 elements
In Chrome the array.splice (C) is the fastest in-place solution (the delete (C) is similar fast - but it left an empty slot in the array (so it does not perform a 'full remove')). The array.slice-splice (H) is the fastest immutable solution. The slowest is array.filter (D and E). You can perform the test on your machine here.
var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var log = (letter,array) => console.log(letter, array.join `,`);
function A(array) {
var index = array.indexOf(5);
delete array[index];
log('A', array);
}
function B(array) {
var index = array.indexOf(5);
var arr = Array.from(array);
arr.splice(index, 1)
log('B', arr);
}
function C(array) {
var index = array.indexOf(5);
array.splice(index, 1);
log('C', array);
}
function D(array) {
var arr = array.filter(item => item !== 5)
log('D', arr);
}
function E(array) {
var index = array.indexOf(5);
var arr = array.filter((item, i) => i !== index)
log('E', arr);
}
function F(array) {
var index = array.indexOf(5);
var arr = array.slice(0, index).concat(array.slice(index + 1))
log('F', arr);
}
function G(array) {
var index = array.indexOf(5);
var arr = [...array.slice(0, index), ...array.slice(index + 1)]
log('G', arr);
}
function H(array) {
var index = array.indexOf(5);
var arr = array.slice(0);
arr.splice(index, 1);
log('H', arr);
}
A([...a]);
B([...a]);
C([...a]);
D([...a]);
E([...a]);
F([...a]);
G([...a]);
H([...a]);
This snippet only presents code used in performance tests - it does not perform tests itself.
Comparison for browsers: Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0
OK, for example you have the array below:
var num = [1, 2, 3, 4, 5];
And we want to delete number 4. You can simply use the below code:
num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];
If you are reusing this function, you write a reusable function which will be attached to the native array function like below:
Array.prototype.remove = Array.prototype.remove || function(x) {
const i = this.indexOf(x);
if(i===-1)
return;
this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}
But how about if you have the below array instead with a few [5]s in the array?
var num = [5, 6, 5, 4, 5, 1, 5];
We need a loop to check them all, but an easier and more efficient way is using built-in JavaScript functions, so we write a function which use a filter like below instead:
const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]
Also there are third-party libraries which do help you to do this, like Lodash or Underscore. For more information, look at lodash _.pull, _.pullAt or _.without.
I'm pretty new to JavaScript and needed this functionality. I merely wrote this:
function removeFromArray(array, item, index) {
while((index = array.indexOf(item)) > -1) {
array.splice(index, 1);
}
}
Then when I want to use it:
//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];
//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");
Output - As expected.
["item1", "item1"]
You may have different needs than I, so you can easily modify it to suit them. I hope this helps someone.
I want to answer based on ECMAScript 6. Assume you have an array like below:
let arr = [1,2,3,4];
If you want to delete at a special index like 2, write the below code:
arr.splice(2, 1); //=> arr became [1,2,4]
But if you want to delete a special item like 3 and you don't know its index, do like below:
arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]
Hint: please use an arrow function for filter callback unless you will get an empty array.
If you have complex objects in the array you can use filters?
In situations where $.inArray or array.splice is not as easy to use. Especially if the objects are perhaps shallow in the array.
E.g. if you have an object with an Id field and you want the object removed from an array:
this.array = this.array.filter(function(element, i) {
return element.id !== idToRemove;
});
Update: This method is recommended only if you cannot use ECMAScript 2015 (formerly known as ES6). If you can use it, other answers here provide much neater implementations.
This gist here will solve your problem, and also deletes all occurrences of the argument instead of just 1 (or a specified value).
Array.prototype.destroy = function(obj){
// Return null if no objects were found and removed
var destroyed = null;
for(var i = 0; i < this.length; i++){
// Use while-loop to find adjacent equal objects
while(this[i] === obj){
// Remove this[i] and store it within destroyed
destroyed = this.splice(i, 1)[0];
}
}
return destroyed;
}
Usage:
var x = [1, 2, 3, 3, true, false, undefined, false];
x.destroy(3); // => 3
x.destroy(false); // => false
x; // => [1, 2, true, undefined]
x.destroy(true); // => true
x.destroy(undefined); // => undefined
x; // => [1, 2]
x.destroy(3); // => null
x; // => [1, 2]
You should never mutate your array as this is against the functional programming pattern. You can create a new array without referencing the one you want to change data of using the ECMAScript 6 method filter;
var myArray = [1, 2, 3, 4, 5, 6];
Suppose you want to remove 5 from the array, you can simply do it like this:
myArray = myArray.filter(value => value !== 5);
This will give you a new array without the value you wanted to remove. So the result will be:
[1, 2, 3, 4, 6]; // 5 has been removed from this array
For further understanding you can read the MDN documentation on Array.filter.
A more modern, ECMAScript 2015 (formerly known as Harmony or ES 6) approach. Given:
const items = [1, 2, 3, 4];
const index = 2;
Then:
items.filter((x, i) => i !== index);
Yielding:
[1, 2, 4]
You can use Babel and a polyfill service to ensure this is well supported across browsers.
You can do a backward loop to make sure not to screw up the indexes, if there are multiple instances of the element.
var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];
/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
if (myArray[i] == myElement) myArray.splice(i, 1);
}
console.log(myArray);

Javascript : Opposite of deal.voters.push(user); [duplicate]

How do I remove a specific value from an array? Something like:
array.remove(value);
Constraints: I have to use core JavaScript. Frameworks are not allowed.
Find the index of the array element you want to remove using indexOf, and then remove that index with splice.
The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.
const array = [2, 5, 9];
console.log(array);
const index = array.indexOf(5);
if (index > -1) { // only splice array when item is found
array.splice(index, 1); // 2nd parameter means remove one item only
}
// array = [2, 9]
console.log(array);
The second parameter of splice is the number of elements to remove. Note that splice modifies the array in place and returns a new array containing the elements that have been removed.
For the reason of completeness, here are functions. The first function removes only a single occurrence (i.e. removing the first match of 5 from [2,5,9,1,5,8,5]), while the second function removes all occurrences:
function removeItemOnce(arr, value) {
var index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
function removeItemAll(arr, value) {
var i = 0;
while (i < arr.length) {
if (arr[i] === value) {
arr.splice(i, 1);
} else {
++i;
}
}
return arr;
}
// Usage
console.log(removeItemOnce([2,5,9,1,5,8,5], 5))
console.log(removeItemAll([2,5,9,1,5,8,5], 5))
In TypeScript, these functions can stay type-safe with a type parameter:
function removeItem<T>(arr: Array<T>, value: T): Array<T> {
const index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
Edited on 2016 October
Do it simple, intuitive and explicit (Occam's razor)
Do it immutable (original array stays unchanged)
Do it with standard JavaScript functions, if your browser doesn't support them - use polyfill
In this code example I use array.filter(...) function to remove unwanted items from an array. This function doesn't change the original array and creates a new one. If your browser doesn't support this function (e.g. Internet Explorer before version 9, or Firefox before version 1.5), consider polyfilling with core-js.
Removing item (ECMA-262 Edition 5 code AKA old style JavaScript)
var value = 3
var arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(function(item) {
return item !== value
})
console.log(arr)
// [ 1, 2, 4, 5 ]
Removing item (ECMAScript 6 code)
let value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
IMPORTANT ECMAScript 6 () => {} arrow function syntax is not supported in Internet Explorer at all, Chrome before version 45, Firefox before version 22, and Safari before version 10. To use ECMAScript 6 syntax in old browsers you can use BabelJS.
Removing multiple items (ECMAScript 7 code)
An additional advantage of this method is that you can remove multiple items
let forDeletion = [2, 3, 5]
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!
console.log(arr)
// [ 1, 4 ]
IMPORTANT array.includes(...) function is not supported in Internet Explorer at all, Chrome before version 47, Firefox before version 43, Safari before version 9, and Edge before version 14 but you can polyfill with core-js.
Removing multiple items (in the future, maybe)
If the "This-Binding Syntax" proposal is ever accepted, you'll be able to do this:
// array-lib.js
export function remove(...forDeletion) {
return this.filter(item => !forDeletion.includes(item))
}
// main.js
import { remove } from './array-lib.js'
let arr = [1, 2, 3, 4, 5, 3]
// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)
console.log(arr)
// [ 1, 4 ]
Try it yourself in BabelJS :)
Reference
Array.prototype.includes
Functional composition
I don't know how you are expecting array.remove(int) to behave. There are three possibilities I can think of that you might want.
To remove an element of an array at an index i:
array.splice(i, 1);
If you want to remove every element with value number from the array:
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] === number) {
array.splice(i, 1);
}
}
If you just want to make the element at index i no longer exist, but you don't want the indexes of the other elements to change:
delete array[i];
It depends on whether you want to keep an empty spot or not.
If you do want an empty slot:
array[index] = undefined;
If you don't want an empty slot:
//To keep the original:
//oldArray = [...array];
//This modifies the array.
array.splice(index, 1);
And if you need the value of that item, you can just store the returned array's element:
var value = array.splice(index, 1)[0];
If you want to remove at either end of the array, you can use array.pop() for the last one or array.shift() for the first one (both return the value of the item as well).
If you don't know the index of the item, you can use array.indexOf(item) to get it (in a if() to get one item or in a while() to get all of them). array.indexOf(item) returns either the index or -1 if not found.
A friend was having issues in Internet Explorer 8 and showed me what he did. I told him it was wrong, and he told me he got the answer here. The current top answer will not work in all browsers (Internet Explorer 8 for example), and it will only remove the first occurrence of the item.
Remove ALL instances from an array
function removeAllInstances(arr, item) {
for (var i = arr.length; i--;) {
if (arr[i] === item) arr.splice(i, 1);
}
}
It loops through the array backwards (since indices and length will change as items are removed) and removes the item if it's found. It works in all browsers.
There are two major approaches
splice(): anArray.splice(index, 1);
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = fruits.splice(2, 1);
// fruits is ['Apple', 'Banana', 'Orange']
// removed is ['Mango']
delete: delete anArray[index];
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = delete fruits(2);
// fruits is ['Apple', 'Banana', undefined, 'Orange']
// removed is true
Be careful when you use the delete for an array. It is good for deleting attributes of objects, but not so good for arrays. It is better to use splice for arrays.
Keep in mind that when you use delete for an array you could get wrong results for anArray.length. In other words, delete would remove the element, but it wouldn't update the value of the length property.
You can also expect to have holes in index numbers after using delete, e.g. you could end up with having indexes 1, 3, 4, 8, 9, and 11 and length as it was before using delete. In that case, all indexed for loops would crash, since indexes are no longer sequential.
If you are forced to use delete for some reason, then you should use for each loops when you need to loop through arrays. As the matter of fact, always avoid using indexed for loops, if possible. That way the code would be more robust and less prone to problems with indexes.
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
var fruits = ['apple', 'banana', 'carrot', 'orange'];
fruits.removeByValue('banana');
console.log(fruits);
// -> ['apple', 'carrot', 'orange']
There isn't any need to use indexOf or splice. However, it performs better if you only want to remove one occurrence of an element.
Find and move (move):
function move(arr, val) {
var j = 0;
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i] !== val) {
arr[j++] = arr[i];
}
}
arr.length = j;
}
Use indexOf and splice (indexof):
function indexof(arr, val) {
var i;
while ((i = arr.indexOf(val)) != -1) {
arr.splice(i, 1);
}
}
Use only splice (splice):
function splice(arr, val) {
for (var i = arr.length; i--;) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
Run-times on Node.js for an array with 1000 elements (averaged over 10,000 runs):
indexof is approximately 10 times slower than move. Even if improved by removing the call to indexOf in splice, it performs much worse than move.
Remove all occurrences:
move 0.0048 ms
indexof 0.0463 ms
splice 0.0359 ms
Remove first occurrence:
move_one 0.0041 ms
indexof_one 0.0021 ms
This provides a predicate instead of a value.
NOTE: it will update the given array, and return the affected rows.
Usage
var removed = helper.remove(arr, row => row.id === 5 );
var removed = helper.removeAll(arr, row => row.name.startsWith('BMW'));
Definition
var helper = {
// Remove and return the first occurrence
remove: function(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) {
return array.splice(i, 1);
}
}
},
// Remove and return all occurrences
removeAll: function(array, predicate) {
var removed = [];
for (var i = 0; i < array.length; ) {
if (predicate(array[i])) {
removed.push(array.splice(i, 1));
continue;
}
i++;
}
return removed;
},
};
You can do it easily with the filter method:
function remove(arrOriginal, elementToRemove){
return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));
This removes all elements from the array and also works faster than a combination of slice and indexOf.
Using filter is an elegant way to achieve this requirement.
filter will not mutate the original array.
const num = 3;
let arr = [1, 2, 3, 4];
const arr2 = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 4]
You can use filter and then assign the result to the original array if you want to achieve a mutation removal behaviour.
const num = 3;
let arr = [1, 2, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
By the way, filter will remove all of the occurrences matched in the condition (not just the first occurrence) like you can see in the following example
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
In case, you just want to remove the first occurrence, you can use the splice method
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
const idx = arr.indexOf(num);
arr.splice(idx, idx !== -1 ? 1 : 0);
console.log(arr); // [1, 2, 3, 3, 4]
John Resig posted a good implementation:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
If you don’t want to extend a global object, you can do something like the following, instead:
// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
var rest = array.slice((to || from) + 1 || array.length);
array.length = from < 0 ? array.length + from : from;
return array.push.apply(array, rest);
};
But the main reason I am posting this is to warn users against the alternative implementation suggested in the comments on that page (Dec 14, 2007):
Array.prototype.remove = function(from, to) {
this.splice(from, (to=[0, from || 1, ++to - from][arguments.length]) < 0 ? this.length + to : to);
return this.length;
};
It seems to work well at first, but through a painful process I discovered it fails when trying to remove the second to last element in an array. For example, if you have a 10-element array and you try to remove the 9th element with this:
myArray.remove(8);
You end up with an 8-element array. I don't know why, but I confirmed John's original implementation doesn't have this problem.
You can use ES6. For example to delete the value '3' in this case:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);
Output :
["1", "2", "4", "5", "6"]
Underscore.js can be used to solve issues with multiple browsers. It uses in-build browser methods if present. If they are absent like in the case of older Internet Explorer versions it uses its own custom methods.
A simple example to remove elements from array (from the website):
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
If you want a new array with the deleted positions removed, you can always delete the specific element and filter out the array. It might need an extension of the array object for browsers that don't implement the filter method, but in the long term it's easier since all you do is this:
var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));
It should display [1, 2, 3, 4, 6].
Here are a few ways to remove an item from an array using JavaScript.
All the method described do not mutate the original array, and instead create a new one.
If you know the index of an item
Suppose you have an array, and you want to remove an item in position i.
One method is to use slice():
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))
console.log(filteredItems)
slice() creates a new array with the indexes it receives. We simply create a new array, from start to the index we want to remove, and concatenate another array from the first position following the one we removed to the end of the array.
If you know the value
In this case, one good option is to use filter(), which offers a more declarative approach:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)
console.log(filteredItems)
This uses the ES6 arrow functions. You can use the traditional functions to support older browsers:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
return item !== valueToRemove
})
console.log(filteredItems)
or you can use Babel and transpile the ES6 code back to ES5 to make it more digestible to old browsers, yet write modern JavaScript in your code.
Removing multiple items
What if instead of a single item, you want to remove many items?
Let's find the simplest solution.
By index
You can just create a function and remove items in series:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const removeItem = (items, i) =>
items.slice(0, i-1).concat(items.slice(i, items.length))
let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]
console.log(filteredItems)
By value
You can search for inclusion inside the callback function:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]
console.log(filteredItems)
Avoid mutating the original array
splice() (not to be confused with slice()) mutates the original array, and should be avoided.
(originally posted on my site https://flaviocopes.com/how-to-remove-item-from-array/)
Check out this code. It works in every major browser.
remove_item = function(arr, value) {
var b = '';
for (b in arr) {
if (arr[b] === value) {
arr.splice(b, 1);
break;
}
}
return arr;
};
var array = [1,3,5,6,5,9,5,3,55]
var res = remove_item(array,5);
console.log(res)
Removing a particular element/string from an array can be done in a one-liner:
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
where:
theArray: the array you want to remove something particular from
stringToRemoveFromArray: the string you want to be removed and 1 is the number of elements you want to remove.
NOTE: If "stringToRemoveFromArray" is not located in the array, this will remove the last element of the array.
It's always good practice to check if the element exists in your array first, before removing it.
if (theArray.indexOf("stringToRemoveFromArray") >= 0){
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}
Depending if you have newer or older version of Ecmascript running on your client's computers:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
OR
var array = ['1','2','3','4','5','6'];
var newArray = array.filter(function(item){ return item !== '3' });
Where '3' is the value you want to be removed from the array.
The array would then become : ['1','2','4','5','6']
ES10
This post summarizes common approaches to element removal from an array as of ECMAScript 2019 (ES10).
1. General cases
1.1. Removing Array element by value using .splice()
| In-place: Yes |
| Removes duplicates: Yes(loop), No(indexOf) |
| By value / index: By index |
If you know the value you want to remove from an array you can use the splice method. First, you must identify the index of the target item. You then use the index as the start element and remove just one element.
// With a 'for' loop
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
for( let i = 0; i < arr.length; i++){
if ( arr[i] === 5) {
arr.splice(i, 1);
}
} // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
// With the .indexOf() method
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
const i = arr.indexOf(5);
arr.splice(i, 1); // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
1.2. Removing Array element using the .filter() method
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
The specific element can be filtered out from the array, by providing a filtering function. Such function is then called for every element in the array.
const value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
1.3. Removing Array element by extending Array.prototype
| In-place: Yes/No (Depends on implementation) |
| Removes duplicates: Yes/No (Depends on implementation) |
| By value / index: By index / By value (Depends on implementation) |
The prototype of Array can be extended with additional methods. Such methods will be then available to use on created arrays.
Note: Extending prototypes of objects from the standard library of JavaScript (like Array) is considered by some as an antipattern.
// In-place, removes all, by value implementation
Array.prototype.remove = function(item) {
for (let i = 0; i < this.length; i++) {
if (this[i] === item) {
this.splice(i, 1);
}
}
}
const arr1 = [1,2,3,1];
arr1.remove(1) // arr1 equals [2,3]
// Non-stationary, removes first, by value implementation
Array.prototype.remove = function(item) {
const arr = this.slice();
for (let i = 0; i < this.length; i++) {
if (arr[i] === item) {
arr.splice(i, 1);
return arr;
}
}
return arr;
}
let arr2 = [1,2,3,1];
arr2 = arr2.remove(1) // arr2 equals [2,3,1]
1.4. Removing Array element using the delete operator
| In-place: Yes |
| Removes duplicates: No |
| By value / index: By index |
Using the delete operator does not affect the length property. Nor does it affect the indexes of subsequent elements. The array becomes sparse, which is a fancy way of saying the deleted item is not removed but becomes undefined.
const arr = [1, 2, 3, 4, 5, 6];
delete arr[4]; // Delete element with index 4
console.log( arr ); // [1, 2, 3, 4, undefined, 6]
The delete operator is designed to remove properties from JavaScript objects, which arrays are objects.
1.5. Removing Array element using Object utilities (>= ES10)
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
ES10 introduced Object.fromEntries, which can be used to create the desired Array from any Array-like object and filter unwanted elements during the process.
const object = [1,2,3,4];
const valueToRemove = 3;
const arr = Object.values(Object.fromEntries(
Object.entries(object)
.filter(([ key, val ]) => val !== valueToRemove)
));
console.log(arr); // [1,2,4]
2. Special cases
2.1 Removing element if it's at the end of the Array
2.1.1. Changing Array length
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
JavaScript Array elements can be removed from the end of an array by setting the length property to a value less than the current value. Any element whose index is greater than or equal to the new length will be removed.
const arr = [1, 2, 3, 4, 5, 6];
arr.length = 5; // Set length to remove element
console.log( arr ); // [1, 2, 3, 4, 5]
2.1.2. Using .pop() method
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The pop method removes the last element of the array, returns that element, and updates the length property. The pop method modifies the array on which it is invoked, This means unlike using delete the last element is removed completely and the array length reduced.
const arr = [1, 2, 3, 4, 5, 6];
arr.pop(); // returns 6
console.log( arr ); // [1, 2, 3, 4, 5]
2.2. Removing element if it's at the beginning of the Array
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The .shift() method works much like the pop method except it removes the first element of a JavaScript array instead of the last. When the element is removed the remaining elements are shifted down.
const arr = [1, 2, 3, 4];
arr.shift(); // returns 1
console.log( arr ); // [2, 3, 4]
2.3. Removing element if it's the only element in the Array
| In-place: Yes |
| Removes duplicates: N/A |
| By value / index: N/A |
The fastest technique is to set an array variable to an empty array.
let arr = [1];
arr = []; //empty array
Alternatively technique from 2.1.1 can be used by setting length to 0.
You can use lodash _.pull (mutate array), _.pullAt (mutate array) or _.without (does't mutate array),
var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']
var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']
var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']
ES6 & without mutation: (October 2016)
const removeByIndex = (list, index) =>
[
...list.slice(0, index),
...list.slice(index + 1)
];
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
console.log(output)
Performance
Today (2019-12-09) I conduct performance tests on macOS v10.13.6 (High Sierra) for chosen solutions. I show delete (A), but I do not use it in comparison with other methods, because it left empty space in the array.
The conclusions
the fastest solution is array.splice (C) (except Safari for small arrays where it has the second time)
for big arrays, array.slice+splice (H) is the fastest immutable solution for Firefox and Safari; Array.from (B) is fastest in Chrome
mutable solutions are usually 1.5x-6x faster than immutable
for small tables on Safari, surprisingly the mutable solution (C) is slower than the immutable solution (G)
Details
In tests, I remove the middle element from the array in different ways. The A, C solutions are in-place. The B, D, E, F, G, H solutions are immutable.
Results for an array with 10 elements
In Chrome the array.splice (C) is the fastest in-place solution. The array.filter (D) is the fastest immutable solution. The slowest is array.slice (F). You can perform the test on your machine here.
Results for an array with 1.000.000 elements
In Chrome the array.splice (C) is the fastest in-place solution (the delete (C) is similar fast - but it left an empty slot in the array (so it does not perform a 'full remove')). The array.slice-splice (H) is the fastest immutable solution. The slowest is array.filter (D and E). You can perform the test on your machine here.
var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var log = (letter,array) => console.log(letter, array.join `,`);
function A(array) {
var index = array.indexOf(5);
delete array[index];
log('A', array);
}
function B(array) {
var index = array.indexOf(5);
var arr = Array.from(array);
arr.splice(index, 1)
log('B', arr);
}
function C(array) {
var index = array.indexOf(5);
array.splice(index, 1);
log('C', array);
}
function D(array) {
var arr = array.filter(item => item !== 5)
log('D', arr);
}
function E(array) {
var index = array.indexOf(5);
var arr = array.filter((item, i) => i !== index)
log('E', arr);
}
function F(array) {
var index = array.indexOf(5);
var arr = array.slice(0, index).concat(array.slice(index + 1))
log('F', arr);
}
function G(array) {
var index = array.indexOf(5);
var arr = [...array.slice(0, index), ...array.slice(index + 1)]
log('G', arr);
}
function H(array) {
var index = array.indexOf(5);
var arr = array.slice(0);
arr.splice(index, 1);
log('H', arr);
}
A([...a]);
B([...a]);
C([...a]);
D([...a]);
E([...a]);
F([...a]);
G([...a]);
H([...a]);
This snippet only presents code used in performance tests - it does not perform tests itself.
Comparison for browsers: Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0
OK, for example you have the array below:
var num = [1, 2, 3, 4, 5];
And we want to delete number 4. You can simply use the below code:
num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];
If you are reusing this function, you write a reusable function which will be attached to the native array function like below:
Array.prototype.remove = Array.prototype.remove || function(x) {
const i = this.indexOf(x);
if(i===-1)
return;
this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}
But how about if you have the below array instead with a few [5]s in the array?
var num = [5, 6, 5, 4, 5, 1, 5];
We need a loop to check them all, but an easier and more efficient way is using built-in JavaScript functions, so we write a function which use a filter like below instead:
const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]
Also there are third-party libraries which do help you to do this, like Lodash or Underscore. For more information, look at lodash _.pull, _.pullAt or _.without.
I'm pretty new to JavaScript and needed this functionality. I merely wrote this:
function removeFromArray(array, item, index) {
while((index = array.indexOf(item)) > -1) {
array.splice(index, 1);
}
}
Then when I want to use it:
//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];
//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");
Output - As expected.
["item1", "item1"]
You may have different needs than I, so you can easily modify it to suit them. I hope this helps someone.
I want to answer based on ECMAScript 6. Assume you have an array like below:
let arr = [1,2,3,4];
If you want to delete at a special index like 2, write the below code:
arr.splice(2, 1); //=> arr became [1,2,4]
But if you want to delete a special item like 3 and you don't know its index, do like below:
arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]
Hint: please use an arrow function for filter callback unless you will get an empty array.
If you have complex objects in the array you can use filters?
In situations where $.inArray or array.splice is not as easy to use. Especially if the objects are perhaps shallow in the array.
E.g. if you have an object with an Id field and you want the object removed from an array:
this.array = this.array.filter(function(element, i) {
return element.id !== idToRemove;
});
Update: This method is recommended only if you cannot use ECMAScript 2015 (formerly known as ES6). If you can use it, other answers here provide much neater implementations.
This gist here will solve your problem, and also deletes all occurrences of the argument instead of just 1 (or a specified value).
Array.prototype.destroy = function(obj){
// Return null if no objects were found and removed
var destroyed = null;
for(var i = 0; i < this.length; i++){
// Use while-loop to find adjacent equal objects
while(this[i] === obj){
// Remove this[i] and store it within destroyed
destroyed = this.splice(i, 1)[0];
}
}
return destroyed;
}
Usage:
var x = [1, 2, 3, 3, true, false, undefined, false];
x.destroy(3); // => 3
x.destroy(false); // => false
x; // => [1, 2, true, undefined]
x.destroy(true); // => true
x.destroy(undefined); // => undefined
x; // => [1, 2]
x.destroy(3); // => null
x; // => [1, 2]
You should never mutate your array as this is against the functional programming pattern. You can create a new array without referencing the one you want to change data of using the ECMAScript 6 method filter;
var myArray = [1, 2, 3, 4, 5, 6];
Suppose you want to remove 5 from the array, you can simply do it like this:
myArray = myArray.filter(value => value !== 5);
This will give you a new array without the value you wanted to remove. So the result will be:
[1, 2, 3, 4, 6]; // 5 has been removed from this array
For further understanding you can read the MDN documentation on Array.filter.
A more modern, ECMAScript 2015 (formerly known as Harmony or ES 6) approach. Given:
const items = [1, 2, 3, 4];
const index = 2;
Then:
items.filter((x, i) => i !== index);
Yielding:
[1, 2, 4]
You can use Babel and a polyfill service to ensure this is well supported across browsers.
You can do a backward loop to make sure not to screw up the indexes, if there are multiple instances of the element.
var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];
/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
if (myArray[i] == myElement) myArray.splice(i, 1);
}
console.log(myArray);

Remove One Object from Array using JavaScript [duplicate]

How do I remove a specific value from an array? Something like:
array.remove(value);
Constraints: I have to use core JavaScript. Frameworks are not allowed.
Find the index of the array element you want to remove using indexOf, and then remove that index with splice.
The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.
const array = [2, 5, 9];
console.log(array);
const index = array.indexOf(5);
if (index > -1) { // only splice array when item is found
array.splice(index, 1); // 2nd parameter means remove one item only
}
// array = [2, 9]
console.log(array);
The second parameter of splice is the number of elements to remove. Note that splice modifies the array in place and returns a new array containing the elements that have been removed.
For the reason of completeness, here are functions. The first function removes only a single occurrence (i.e. removing the first match of 5 from [2,5,9,1,5,8,5]), while the second function removes all occurrences:
function removeItemOnce(arr, value) {
var index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
function removeItemAll(arr, value) {
var i = 0;
while (i < arr.length) {
if (arr[i] === value) {
arr.splice(i, 1);
} else {
++i;
}
}
return arr;
}
// Usage
console.log(removeItemOnce([2,5,9,1,5,8,5], 5))
console.log(removeItemAll([2,5,9,1,5,8,5], 5))
In TypeScript, these functions can stay type-safe with a type parameter:
function removeItem<T>(arr: Array<T>, value: T): Array<T> {
const index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
Edited on 2016 October
Do it simple, intuitive and explicit (Occam's razor)
Do it immutable (original array stays unchanged)
Do it with standard JavaScript functions, if your browser doesn't support them - use polyfill
In this code example I use array.filter(...) function to remove unwanted items from an array. This function doesn't change the original array and creates a new one. If your browser doesn't support this function (e.g. Internet Explorer before version 9, or Firefox before version 1.5), consider polyfilling with core-js.
Removing item (ECMA-262 Edition 5 code AKA old style JavaScript)
var value = 3
var arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(function(item) {
return item !== value
})
console.log(arr)
// [ 1, 2, 4, 5 ]
Removing item (ECMAScript 6 code)
let value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
IMPORTANT ECMAScript 6 () => {} arrow function syntax is not supported in Internet Explorer at all, Chrome before version 45, Firefox before version 22, and Safari before version 10. To use ECMAScript 6 syntax in old browsers you can use BabelJS.
Removing multiple items (ECMAScript 7 code)
An additional advantage of this method is that you can remove multiple items
let forDeletion = [2, 3, 5]
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => !forDeletion.includes(item))
// !!! Read below about array.includes(...) support !!!
console.log(arr)
// [ 1, 4 ]
IMPORTANT array.includes(...) function is not supported in Internet Explorer at all, Chrome before version 47, Firefox before version 43, Safari before version 9, and Edge before version 14 but you can polyfill with core-js.
Removing multiple items (in the future, maybe)
If the "This-Binding Syntax" proposal is ever accepted, you'll be able to do this:
// array-lib.js
export function remove(...forDeletion) {
return this.filter(item => !forDeletion.includes(item))
}
// main.js
import { remove } from './array-lib.js'
let arr = [1, 2, 3, 4, 5, 3]
// :: This-Binding Syntax Proposal
// using "remove" function as "virtual method"
// without extending Array.prototype
arr = arr::remove(2, 3, 5)
console.log(arr)
// [ 1, 4 ]
Try it yourself in BabelJS :)
Reference
Array.prototype.includes
Functional composition
I don't know how you are expecting array.remove(int) to behave. There are three possibilities I can think of that you might want.
To remove an element of an array at an index i:
array.splice(i, 1);
If you want to remove every element with value number from the array:
for (var i = array.length - 1; i >= 0; i--) {
if (array[i] === number) {
array.splice(i, 1);
}
}
If you just want to make the element at index i no longer exist, but you don't want the indexes of the other elements to change:
delete array[i];
It depends on whether you want to keep an empty spot or not.
If you do want an empty slot:
array[index] = undefined;
If you don't want an empty slot:
//To keep the original:
//oldArray = [...array];
//This modifies the array.
array.splice(index, 1);
And if you need the value of that item, you can just store the returned array's element:
var value = array.splice(index, 1)[0];
If you want to remove at either end of the array, you can use array.pop() for the last one or array.shift() for the first one (both return the value of the item as well).
If you don't know the index of the item, you can use array.indexOf(item) to get it (in a if() to get one item or in a while() to get all of them). array.indexOf(item) returns either the index or -1 if not found.
A friend was having issues in Internet Explorer 8 and showed me what he did. I told him it was wrong, and he told me he got the answer here. The current top answer will not work in all browsers (Internet Explorer 8 for example), and it will only remove the first occurrence of the item.
Remove ALL instances from an array
function removeAllInstances(arr, item) {
for (var i = arr.length; i--;) {
if (arr[i] === item) arr.splice(i, 1);
}
}
It loops through the array backwards (since indices and length will change as items are removed) and removes the item if it's found. It works in all browsers.
There are two major approaches
splice(): anArray.splice(index, 1);
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = fruits.splice(2, 1);
// fruits is ['Apple', 'Banana', 'Orange']
// removed is ['Mango']
delete: delete anArray[index];
let fruits = ['Apple', 'Banana', 'Mango', 'Orange']
let removed = delete fruits(2);
// fruits is ['Apple', 'Banana', undefined, 'Orange']
// removed is true
Be careful when you use the delete for an array. It is good for deleting attributes of objects, but not so good for arrays. It is better to use splice for arrays.
Keep in mind that when you use delete for an array you could get wrong results for anArray.length. In other words, delete would remove the element, but it wouldn't update the value of the length property.
You can also expect to have holes in index numbers after using delete, e.g. you could end up with having indexes 1, 3, 4, 8, 9, and 11 and length as it was before using delete. In that case, all indexed for loops would crash, since indexes are no longer sequential.
If you are forced to use delete for some reason, then you should use for each loops when you need to loop through arrays. As the matter of fact, always avoid using indexed for loops, if possible. That way the code would be more robust and less prone to problems with indexes.
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
var fruits = ['apple', 'banana', 'carrot', 'orange'];
fruits.removeByValue('banana');
console.log(fruits);
// -> ['apple', 'carrot', 'orange']
There isn't any need to use indexOf or splice. However, it performs better if you only want to remove one occurrence of an element.
Find and move (move):
function move(arr, val) {
var j = 0;
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i] !== val) {
arr[j++] = arr[i];
}
}
arr.length = j;
}
Use indexOf and splice (indexof):
function indexof(arr, val) {
var i;
while ((i = arr.indexOf(val)) != -1) {
arr.splice(i, 1);
}
}
Use only splice (splice):
function splice(arr, val) {
for (var i = arr.length; i--;) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
Run-times on Node.js for an array with 1000 elements (averaged over 10,000 runs):
indexof is approximately 10 times slower than move. Even if improved by removing the call to indexOf in splice, it performs much worse than move.
Remove all occurrences:
move 0.0048 ms
indexof 0.0463 ms
splice 0.0359 ms
Remove first occurrence:
move_one 0.0041 ms
indexof_one 0.0021 ms
This provides a predicate instead of a value.
NOTE: it will update the given array, and return the affected rows.
Usage
var removed = helper.remove(arr, row => row.id === 5 );
var removed = helper.removeAll(arr, row => row.name.startsWith('BMW'));
Definition
var helper = {
// Remove and return the first occurrence
remove: function(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) {
return array.splice(i, 1);
}
}
},
// Remove and return all occurrences
removeAll: function(array, predicate) {
var removed = [];
for (var i = 0; i < array.length; ) {
if (predicate(array[i])) {
removed.push(array.splice(i, 1));
continue;
}
i++;
}
return removed;
},
};
You can do it easily with the filter method:
function remove(arrOriginal, elementToRemove){
return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log(remove([1, 2, 1, 0, 3, 1, 4], 1));
This removes all elements from the array and also works faster than a combination of slice and indexOf.
Using filter is an elegant way to achieve this requirement.
filter will not mutate the original array.
const num = 3;
let arr = [1, 2, 3, 4];
const arr2 = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 3, 4]
console.log(arr2); // [1, 2, 4]
You can use filter and then assign the result to the original array if you want to achieve a mutation removal behaviour.
const num = 3;
let arr = [1, 2, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
By the way, filter will remove all of the occurrences matched in the condition (not just the first occurrence) like you can see in the following example
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
arr = arr.filter(x => x !== num);
console.log(arr); // [1, 2, 4]
In case, you just want to remove the first occurrence, you can use the splice method
const num = 3;
let arr = [1, 2, 3, 3, 3, 4];
const idx = arr.indexOf(num);
arr.splice(idx, idx !== -1 ? 1 : 0);
console.log(arr); // [1, 2, 3, 3, 4]
John Resig posted a good implementation:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
If you don’t want to extend a global object, you can do something like the following, instead:
// Array Remove - By John Resig (MIT Licensed)
Array.remove = function(array, from, to) {
var rest = array.slice((to || from) + 1 || array.length);
array.length = from < 0 ? array.length + from : from;
return array.push.apply(array, rest);
};
But the main reason I am posting this is to warn users against the alternative implementation suggested in the comments on that page (Dec 14, 2007):
Array.prototype.remove = function(from, to) {
this.splice(from, (to=[0, from || 1, ++to - from][arguments.length]) < 0 ? this.length + to : to);
return this.length;
};
It seems to work well at first, but through a painful process I discovered it fails when trying to remove the second to last element in an array. For example, if you have a 10-element array and you try to remove the 9th element with this:
myArray.remove(8);
You end up with an 8-element array. I don't know why, but I confirmed John's original implementation doesn't have this problem.
You can use ES6. For example to delete the value '3' in this case:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
console.log(newArray);
Output :
["1", "2", "4", "5", "6"]
Underscore.js can be used to solve issues with multiple browsers. It uses in-build browser methods if present. If they are absent like in the case of older Internet Explorer versions it uses its own custom methods.
A simple example to remove elements from array (from the website):
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]
If you want a new array with the deleted positions removed, you can always delete the specific element and filter out the array. It might need an extension of the array object for browsers that don't implement the filter method, but in the long term it's easier since all you do is this:
var my_array = [1, 2, 3, 4, 5, 6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));
It should display [1, 2, 3, 4, 6].
Here are a few ways to remove an item from an array using JavaScript.
All the method described do not mutate the original array, and instead create a new one.
If you know the index of an item
Suppose you have an array, and you want to remove an item in position i.
One method is to use slice():
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i).concat(items.slice(i+1, items.length))
console.log(filteredItems)
slice() creates a new array with the indexes it receives. We simply create a new array, from start to the index we want to remove, and concatenate another array from the first position following the one we removed to the end of the array.
If you know the value
In this case, one good option is to use filter(), which offers a more declarative approach:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(item => item !== valueToRemove)
console.log(filteredItems)
This uses the ES6 arrow functions. You can use the traditional functions to support older browsers:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valueToRemove = 'c'
const filteredItems = items.filter(function(item) {
return item !== valueToRemove
})
console.log(filteredItems)
or you can use Babel and transpile the ES6 code back to ES5 to make it more digestible to old browsers, yet write modern JavaScript in your code.
Removing multiple items
What if instead of a single item, you want to remove many items?
Let's find the simplest solution.
By index
You can just create a function and remove items in series:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const removeItem = (items, i) =>
items.slice(0, i-1).concat(items.slice(i, items.length))
let filteredItems = removeItem(items, 3)
filteredItems = removeItem(filteredItems, 5)
//["a", "b", "c", "d"]
console.log(filteredItems)
By value
You can search for inclusion inside the callback function:
const items = ['a', 'b', 'c', 'd', 'e', 'f']
const valuesToRemove = ['c', 'd']
const filteredItems = items.filter(item => !valuesToRemove.includes(item))
// ["a", "b", "e", "f"]
console.log(filteredItems)
Avoid mutating the original array
splice() (not to be confused with slice()) mutates the original array, and should be avoided.
(originally posted on my site https://flaviocopes.com/how-to-remove-item-from-array/)
Check out this code. It works in every major browser.
remove_item = function(arr, value) {
var b = '';
for (b in arr) {
if (arr[b] === value) {
arr.splice(b, 1);
break;
}
}
return arr;
};
var array = [1,3,5,6,5,9,5,3,55]
var res = remove_item(array,5);
console.log(res)
Removing a particular element/string from an array can be done in a one-liner:
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
where:
theArray: the array you want to remove something particular from
stringToRemoveFromArray: the string you want to be removed and 1 is the number of elements you want to remove.
NOTE: If "stringToRemoveFromArray" is not located in the array, this will remove the last element of the array.
It's always good practice to check if the element exists in your array first, before removing it.
if (theArray.indexOf("stringToRemoveFromArray") >= 0){
theArray.splice(theArray.indexOf("stringToRemoveFromArray"), 1);
}
Depending if you have newer or older version of Ecmascript running on your client's computers:
var array=['1','2','3','4','5','6']
var newArray = array.filter((value)=>value!='3');
OR
var array = ['1','2','3','4','5','6'];
var newArray = array.filter(function(item){ return item !== '3' });
Where '3' is the value you want to be removed from the array.
The array would then become : ['1','2','4','5','6']
ES10
This post summarizes common approaches to element removal from an array as of ECMAScript 2019 (ES10).
1. General cases
1.1. Removing Array element by value using .splice()
| In-place: Yes |
| Removes duplicates: Yes(loop), No(indexOf) |
| By value / index: By index |
If you know the value you want to remove from an array you can use the splice method. First, you must identify the index of the target item. You then use the index as the start element and remove just one element.
// With a 'for' loop
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
for( let i = 0; i < arr.length; i++){
if ( arr[i] === 5) {
arr.splice(i, 1);
}
} // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
// With the .indexOf() method
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
const i = arr.indexOf(5);
arr.splice(i, 1); // => [1, 2, 3, 4, 6, 7, 8, 9, 0]
1.2. Removing Array element using the .filter() method
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
The specific element can be filtered out from the array, by providing a filtering function. Such function is then called for every element in the array.
const value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
1.3. Removing Array element by extending Array.prototype
| In-place: Yes/No (Depends on implementation) |
| Removes duplicates: Yes/No (Depends on implementation) |
| By value / index: By index / By value (Depends on implementation) |
The prototype of Array can be extended with additional methods. Such methods will be then available to use on created arrays.
Note: Extending prototypes of objects from the standard library of JavaScript (like Array) is considered by some as an antipattern.
// In-place, removes all, by value implementation
Array.prototype.remove = function(item) {
for (let i = 0; i < this.length; i++) {
if (this[i] === item) {
this.splice(i, 1);
}
}
}
const arr1 = [1,2,3,1];
arr1.remove(1) // arr1 equals [2,3]
// Non-stationary, removes first, by value implementation
Array.prototype.remove = function(item) {
const arr = this.slice();
for (let i = 0; i < this.length; i++) {
if (arr[i] === item) {
arr.splice(i, 1);
return arr;
}
}
return arr;
}
let arr2 = [1,2,3,1];
arr2 = arr2.remove(1) // arr2 equals [2,3,1]
1.4. Removing Array element using the delete operator
| In-place: Yes |
| Removes duplicates: No |
| By value / index: By index |
Using the delete operator does not affect the length property. Nor does it affect the indexes of subsequent elements. The array becomes sparse, which is a fancy way of saying the deleted item is not removed but becomes undefined.
const arr = [1, 2, 3, 4, 5, 6];
delete arr[4]; // Delete element with index 4
console.log( arr ); // [1, 2, 3, 4, undefined, 6]
The delete operator is designed to remove properties from JavaScript objects, which arrays are objects.
1.5. Removing Array element using Object utilities (>= ES10)
| In-place: No |
| Removes duplicates: Yes |
| By value / index: By value |
ES10 introduced Object.fromEntries, which can be used to create the desired Array from any Array-like object and filter unwanted elements during the process.
const object = [1,2,3,4];
const valueToRemove = 3;
const arr = Object.values(Object.fromEntries(
Object.entries(object)
.filter(([ key, val ]) => val !== valueToRemove)
));
console.log(arr); // [1,2,4]
2. Special cases
2.1 Removing element if it's at the end of the Array
2.1.1. Changing Array length
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
JavaScript Array elements can be removed from the end of an array by setting the length property to a value less than the current value. Any element whose index is greater than or equal to the new length will be removed.
const arr = [1, 2, 3, 4, 5, 6];
arr.length = 5; // Set length to remove element
console.log( arr ); // [1, 2, 3, 4, 5]
2.1.2. Using .pop() method
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The pop method removes the last element of the array, returns that element, and updates the length property. The pop method modifies the array on which it is invoked, This means unlike using delete the last element is removed completely and the array length reduced.
const arr = [1, 2, 3, 4, 5, 6];
arr.pop(); // returns 6
console.log( arr ); // [1, 2, 3, 4, 5]
2.2. Removing element if it's at the beginning of the Array
| In-place: Yes |
| Removes duplicates: No |
| By value / index: N/A |
The .shift() method works much like the pop method except it removes the first element of a JavaScript array instead of the last. When the element is removed the remaining elements are shifted down.
const arr = [1, 2, 3, 4];
arr.shift(); // returns 1
console.log( arr ); // [2, 3, 4]
2.3. Removing element if it's the only element in the Array
| In-place: Yes |
| Removes duplicates: N/A |
| By value / index: N/A |
The fastest technique is to set an array variable to an empty array.
let arr = [1];
arr = []; //empty array
Alternatively technique from 2.1.1 can be used by setting length to 0.
You can use lodash _.pull (mutate array), _.pullAt (mutate array) or _.without (does't mutate array),
var array1 = ['a', 'b', 'c', 'd']
_.pull(array1, 'c')
console.log(array1) // ['a', 'b', 'd']
var array2 = ['e', 'f', 'g', 'h']
_.pullAt(array2, 0)
console.log(array2) // ['f', 'g', 'h']
var array3 = ['i', 'j', 'k', 'l']
var newArray = _.without(array3, 'i') // ['j', 'k', 'l']
console.log(array3) // ['i', 'j', 'k', 'l']
ES6 & without mutation: (October 2016)
const removeByIndex = (list, index) =>
[
...list.slice(0, index),
...list.slice(index + 1)
];
output = removeByIndex([33,22,11,44],1) //=> [33,11,44]
console.log(output)
Performance
Today (2019-12-09) I conduct performance tests on macOS v10.13.6 (High Sierra) for chosen solutions. I show delete (A), but I do not use it in comparison with other methods, because it left empty space in the array.
The conclusions
the fastest solution is array.splice (C) (except Safari for small arrays where it has the second time)
for big arrays, array.slice+splice (H) is the fastest immutable solution for Firefox and Safari; Array.from (B) is fastest in Chrome
mutable solutions are usually 1.5x-6x faster than immutable
for small tables on Safari, surprisingly the mutable solution (C) is slower than the immutable solution (G)
Details
In tests, I remove the middle element from the array in different ways. The A, C solutions are in-place. The B, D, E, F, G, H solutions are immutable.
Results for an array with 10 elements
In Chrome the array.splice (C) is the fastest in-place solution. The array.filter (D) is the fastest immutable solution. The slowest is array.slice (F). You can perform the test on your machine here.
Results for an array with 1.000.000 elements
In Chrome the array.splice (C) is the fastest in-place solution (the delete (C) is similar fast - but it left an empty slot in the array (so it does not perform a 'full remove')). The array.slice-splice (H) is the fastest immutable solution. The slowest is array.filter (D and E). You can perform the test on your machine here.
var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var log = (letter,array) => console.log(letter, array.join `,`);
function A(array) {
var index = array.indexOf(5);
delete array[index];
log('A', array);
}
function B(array) {
var index = array.indexOf(5);
var arr = Array.from(array);
arr.splice(index, 1)
log('B', arr);
}
function C(array) {
var index = array.indexOf(5);
array.splice(index, 1);
log('C', array);
}
function D(array) {
var arr = array.filter(item => item !== 5)
log('D', arr);
}
function E(array) {
var index = array.indexOf(5);
var arr = array.filter((item, i) => i !== index)
log('E', arr);
}
function F(array) {
var index = array.indexOf(5);
var arr = array.slice(0, index).concat(array.slice(index + 1))
log('F', arr);
}
function G(array) {
var index = array.indexOf(5);
var arr = [...array.slice(0, index), ...array.slice(index + 1)]
log('G', arr);
}
function H(array) {
var index = array.indexOf(5);
var arr = array.slice(0);
arr.splice(index, 1);
log('H', arr);
}
A([...a]);
B([...a]);
C([...a]);
D([...a]);
E([...a]);
F([...a]);
G([...a]);
H([...a]);
This snippet only presents code used in performance tests - it does not perform tests itself.
Comparison for browsers: Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0
OK, for example you have the array below:
var num = [1, 2, 3, 4, 5];
And we want to delete number 4. You can simply use the below code:
num.splice(num.indexOf(4), 1); // num will be [1, 2, 3, 5];
If you are reusing this function, you write a reusable function which will be attached to the native array function like below:
Array.prototype.remove = Array.prototype.remove || function(x) {
const i = this.indexOf(x);
if(i===-1)
return;
this.splice(i, 1); // num.remove(5) === [1, 2, 3];
}
But how about if you have the below array instead with a few [5]s in the array?
var num = [5, 6, 5, 4, 5, 1, 5];
We need a loop to check them all, but an easier and more efficient way is using built-in JavaScript functions, so we write a function which use a filter like below instead:
const _removeValue = (arr, x) => arr.filter(n => n!==x);
//_removeValue([1, 2, 3, 4, 5, 5, 6, 5], 5) // Return [1, 2, 3, 4, 6]
Also there are third-party libraries which do help you to do this, like Lodash or Underscore. For more information, look at lodash _.pull, _.pullAt or _.without.
I'm pretty new to JavaScript and needed this functionality. I merely wrote this:
function removeFromArray(array, item, index) {
while((index = array.indexOf(item)) > -1) {
array.splice(index, 1);
}
}
Then when I want to use it:
//Set-up some dummy data
var dummyObj = {name:"meow"};
var dummyArray = [dummyObj, "item1", "item1", "item2"];
//Remove the dummy data
removeFromArray(dummyArray, dummyObj);
removeFromArray(dummyArray, "item2");
Output - As expected.
["item1", "item1"]
You may have different needs than I, so you can easily modify it to suit them. I hope this helps someone.
I want to answer based on ECMAScript 6. Assume you have an array like below:
let arr = [1,2,3,4];
If you want to delete at a special index like 2, write the below code:
arr.splice(2, 1); //=> arr became [1,2,4]
But if you want to delete a special item like 3 and you don't know its index, do like below:
arr = arr.filter(e => e !== 3); //=> arr became [1,2,4]
Hint: please use an arrow function for filter callback unless you will get an empty array.
If you have complex objects in the array you can use filters?
In situations where $.inArray or array.splice is not as easy to use. Especially if the objects are perhaps shallow in the array.
E.g. if you have an object with an Id field and you want the object removed from an array:
this.array = this.array.filter(function(element, i) {
return element.id !== idToRemove;
});
Update: This method is recommended only if you cannot use ECMAScript 2015 (formerly known as ES6). If you can use it, other answers here provide much neater implementations.
This gist here will solve your problem, and also deletes all occurrences of the argument instead of just 1 (or a specified value).
Array.prototype.destroy = function(obj){
// Return null if no objects were found and removed
var destroyed = null;
for(var i = 0; i < this.length; i++){
// Use while-loop to find adjacent equal objects
while(this[i] === obj){
// Remove this[i] and store it within destroyed
destroyed = this.splice(i, 1)[0];
}
}
return destroyed;
}
Usage:
var x = [1, 2, 3, 3, true, false, undefined, false];
x.destroy(3); // => 3
x.destroy(false); // => false
x; // => [1, 2, true, undefined]
x.destroy(true); // => true
x.destroy(undefined); // => undefined
x; // => [1, 2]
x.destroy(3); // => null
x; // => [1, 2]
You should never mutate your array as this is against the functional programming pattern. You can create a new array without referencing the one you want to change data of using the ECMAScript 6 method filter;
var myArray = [1, 2, 3, 4, 5, 6];
Suppose you want to remove 5 from the array, you can simply do it like this:
myArray = myArray.filter(value => value !== 5);
This will give you a new array without the value you wanted to remove. So the result will be:
[1, 2, 3, 4, 6]; // 5 has been removed from this array
For further understanding you can read the MDN documentation on Array.filter.
A more modern, ECMAScript 2015 (formerly known as Harmony or ES 6) approach. Given:
const items = [1, 2, 3, 4];
const index = 2;
Then:
items.filter((x, i) => i !== index);
Yielding:
[1, 2, 4]
You can use Babel and a polyfill service to ensure this is well supported across browsers.
You can do a backward loop to make sure not to screw up the indexes, if there are multiple instances of the element.
var myElement = "chocolate";
var myArray = ['chocolate', 'poptart', 'poptart', 'poptart', 'chocolate', 'poptart', 'poptart', 'chocolate'];
/* Important code */
for (var i = myArray.length - 1; i >= 0; i--) {
if (myArray[i] == myElement) myArray.splice(i, 1);
}
console.log(myArray);

What is the most elegant way to insert objects between array elements?

I'm sure there are many ways to achieve that but I'm looking for something "elegant".
a = [
'a',
'b',
'c'
];
magicArrayJoin(a, {value: 255} ); // insert the same object between each item
result == [
'a',
{value: 255},
'b',
{value: 255}
'c'
];
All proposals are welcome. :)
One-liner using plain ES6:
const interleave = (arr, thing) => [].concat(...arr.map(n => [n, thing])).slice(0, -1)
Usage:
interleave(['foo', 'bar', 'baz'], 'avocado')
Prints:
> ["foo", "avocado", "bar", "avocado", "baz"]
You can do it with flatMap. It can be found from lodash for example
_.flatMap([1,2,3,4], (value, index, array) =>
array.length -1 !== index // check for the last item
? [value, "s"]
: value
);
ouputs
[1, "s", 2, "s", 3, "s", 4]
Update
Array#flatMap proposal is in the works so in future this should work:
[1, 2, 3, 4].flatMap(
(value, index, array) =>
array.length - 1 !== index // check for the last item
? [value, "s"]
: value,
);
In my opinion the most elegant way to do this is the following one:
ES6 syntax version
const insertIntoArray = (arr, value) => {
return arr.reduce((result, element, index, array) => {
result.push(element);
if (index < array.length - 1) {
result.push(value);
}
return result;
}, []);
};
Usage:
insertIntoArray([1, 2, 3], 'x'); // => [1, 'x', 2, 'x', 3]
An ordinary loop seems to be the best:
function intersperse(arr, el) {
var res = [], i=0;
if (i < arr.length)
res.push(arr[i++]);
while (i < arr.length)
res.push(el, arr[i++]);
return res;
}
If you're looking for something elegant, it would probably have to use some kind of concatMap, as in
function concatMap(arr, fn) { return [].concat.apply([], arr.map(fn)); }
function intersperse(arr, el) { return concatMap(arr, x => [el, x]).slice(1); }
Use ES6 flatMap function.
const insertBetween = (ele, array) => {
return array.flatMap((x) => [ele, x]).slice(1);
};
insertBetween('+', [1, 2, 3]);
Immutable solution
When reducing an array the reduce function should not mutate the array but return a new value (in this case a new array). That way the changes will be only applied to the returned array and not the original one and side effects will be avoided.
const insertBetween = (insertee, array) => array.reduce(
(acc, item, i, { length }) => {
if (i && i < length) {
return [...acc, insertee, item];
}
return [...acc, item];
},
[]
);
Ramda has intersperse method that:
Creates a new list with the separator interposed between elements.
Code:
R.intersperse({name: 'separator'}, ['one', 'two', 'three']);
Result:
[
'one',
{name: 'separator'},
'two',
{name: 'separator'},
'three'
]
This worked for me:
a.map(val = [val, {value: 255}]).flat()
You can achieve this using reduce (it is also immutable).
const insertBetween = (insertion, array) =>
array.reduce(
(newArray, member, i, array) =>
i < array.length - 1
? newArray.concat(member, insertion)
: newArray.concat(member),
[]
);
const result = insertBetween('and', [1, 2, 3]);
console.log(result);
// outputs;
// [
// 1,
// 'and',
// 2,
// 'and',
// 3
// ]
Or in older JS syntax;
function insertBetween(insertion, array) {
const indexOfLastItem = array.length - 1;
return array.reduce(withInsertion, []);
function withInsertion(newArray, item, index, array) {
return index < indexOfLastItem
? newArray.concat(item, insertion)
: newArray.concat(item);
}
}
const result = insertBetween('and', [1, 2, 3]);
console.log(result);
// outputs;
// [
// 1,
// 'and',
// 2,
// 'and',
// 3
// ]
I really in favor of #Vidul 's comments, which is very logical and concise! I myself also came up with splice(), but missed %. However, most of the braces seem unnecessary as an oneliner. It can be further simplified as
for (var i = 0; i < a.length; i++) if (i % 2) a.splice(i, 0, {value: 255});
function insertObject(arr, obj) {
var result = [];
function insert(element, index) {
result.push(element);
if (index + 1 < arr.length) {
result.push(obj);
}
}
arr.forEach(insert);
return result;
}
var a = [1, 2, 3, 4];
insertObject(a, {
test: 'test'
});
Using splice as Kamen suggests, you could do something like:
const numSeparators = arr.length - 1;
for (let i = 1; i <= numSeparators; i++) {
const index = (i * 2) - 1;
arr.splice(index, 0, { value: 255 });
}
for a simple purely functional way I suggest doing it this way:
const magicArrayJoin = (array, el) =>
array.length ?
array.slice(1).reduce((acc, cur) => acc.concat([el, cur]), [array[0]]) :
[]
p.n. this way is not the most performant one in javascript
ES6:
const arrayWithSeparator = array.reduce((a, i) => a.length ? a.push(separator) && a.push(i) && a : a.push(u) && a, [])
Array.splice() should do the job like so:
a.splice(1, 0, {value : 255})
The first argument is the position at which you want to delete or insert elements, the second is the delete count, the third (optional) is the new element[s] you want to insert.

How can I create every combination possible for the contents of two arrays?

I have two arrays:
var array1 = ["A", "B", "C"];
var array2 = ["1", "2", "3"];
How can I set another array to contain every combination of the above, so that:
var combos = ["A1", "A2", "A3", "B1", "B2", "B3", "C1", "C2", "C3"];
Or if you'd like to create combinations with an arbitrary number of arrays of arbitrary sizes...(I'm sure you can do this recursively, but since this isn't a job interview, I'm instead using an iterative "odometer" for this...it increments a "number" with each digit a "base-n" digit based on the length of each array)...for example...
combineArrays([ ["A","B","C"],
["+", "-", "*", "/"],
["1","2"] ] )
...returns...
[
"A+1","A+2","A-1", "A-2",
"A*1", "A*2", "A/1", "A/2",
"B+1","B+2","B-1", "B-2",
"B*1", "B*2", "B/1", "B/2",
"C+1","C+2","C-1", "C-2",
"C*1", "C*2", "C/1", "C/2"
]
...each of these corresponding to an "odometer" value that
picks an index from each array...
[0,0,0], [0,0,1], [0,1,0], [0,1,1]
[0,2,0], [0,2,1], [0,3,0], [0,3,1]
[1,0,0], [1,0,1], [1,1,0], [1,1,1]
[1,2,0], [1,2,1], [1,3,0], [1,3,1]
[2,0,0], [2,0,1], [2,1,0], [2,1,1]
[2,2,0], [2,2,1], [2,3,0], [2,3,1]
The "odometer" method allows you to easily generate
the type of output you want, not just the concatenated strings
like we have here. Besides that, by avoiding recursion
we avoid the possibility of -- dare I say it? -- a stack overflow...
function combineArrays( array_of_arrays ){
// First, handle some degenerate cases...
if( ! array_of_arrays ){
// Or maybe we should toss an exception...?
return [];
}
if( ! Array.isArray( array_of_arrays ) ){
// Or maybe we should toss an exception...?
return [];
}
if( array_of_arrays.length == 0 ){
return [];
}
for( let i = 0 ; i < array_of_arrays.length; i++ ){
if( ! Array.isArray(array_of_arrays[i]) || array_of_arrays[i].length == 0 ){
// If any of the arrays in array_of_arrays are not arrays or zero-length, return an empty array...
return [];
}
}
// Done with degenerate cases...
// Start "odometer" with a 0 for each array in array_of_arrays.
let odometer = new Array( array_of_arrays.length );
odometer.fill( 0 );
let output = [];
let newCombination = formCombination( odometer, array_of_arrays );
output.push( newCombination );
while ( odometer_increment( odometer, array_of_arrays ) ){
newCombination = formCombination( odometer, array_of_arrays );
output.push( newCombination );
}
return output;
}/* combineArrays() */
// Translate "odometer" to combinations from array_of_arrays
function formCombination( odometer, array_of_arrays ){
// In Imperative Programmingese (i.e., English):
// let s_output = "";
// for( let i=0; i < odometer.length; i++ ){
// s_output += "" + array_of_arrays[i][odometer[i]];
// }
// return s_output;
// In Functional Programmingese (Henny Youngman one-liner):
return odometer.reduce(
function(accumulator, odometer_value, odometer_index){
return "" + accumulator + array_of_arrays[odometer_index][odometer_value];
},
""
);
}/* formCombination() */
function odometer_increment( odometer, array_of_arrays ){
// Basically, work you way from the rightmost digit of the "odometer"...
// if you're able to increment without cycling that digit back to zero,
// you're all done, otherwise, cycle that digit to zero and go one digit to the
// left, and begin again until you're able to increment a digit
// without cycling it...simple, huh...?
for( let i_odometer_digit = odometer.length-1; i_odometer_digit >=0; i_odometer_digit-- ){
let maxee = array_of_arrays[i_odometer_digit].length - 1;
if( odometer[i_odometer_digit] + 1 <= maxee ){
// increment, and you're done...
odometer[i_odometer_digit]++;
return true;
}
else{
if( i_odometer_digit - 1 < 0 ){
// No more digits left to increment, end of the line...
return false;
}
else{
// Can't increment this digit, cycle it to zero and continue
// the loop to go over to the next digit...
odometer[i_odometer_digit]=0;
continue;
}
}
}/* for( let odometer_digit = odometer.length-1; odometer_digit >=0; odometer_digit-- ) */
}/* odometer_increment() */
Just in case anyone is looking for Array.map solution
var array1=["A","B","C"];
var array2=["1","2","3","4"];
console.log(array1.flatMap(d => array2.map(v => d + v)))
Seeing a lot of for loops in all of the answers...
Here's a recursive solution I came up with that will find all combinations of N number of arrays by taking 1 element from each array:
const array1=["A","B","C"]
const array2=["1","2","3"]
const array3=["red","blue","green"]
const combine = ([head, ...[headTail, ...tailTail]]) => {
if (!headTail) return head
const combined = headTail.reduce((acc, x) => {
return acc.concat(head.map(h => `${h}${x}`))
}, [])
return combine([combined, ...tailTail])
}
console.log('With your example arrays:', combine([array1, array2]))
console.log('With N arrays:', combine([array1, array2, array3]))
//-----------UPDATE BELOW FOR COMMENT---------
// With objects
const array4=[{letter: "A"}, {letter: "B"}, {letter: "C"}]
const array5=[{number: 1}, {number: 2}, {number: 3}]
const array6=[{color: "RED"}, {color: "BLUE"}, {color: "GREEN"}]
const combineObjects = ([head, ...[headTail, ...tailTail]]) => {
if (!headTail) return head
const combined = headTail.reduce((acc, x) => {
return acc.concat(head.map(h => ({...h, ...x})))
}, [])
return combineObjects([combined, ...tailTail])
}
console.log('With arrays of objects:', combineObjects([array4, array5, array6]))
A loop of this form
combos = [] //or combos = new Array(2);
for(var i = 0; i < array1.length; i++)
{
for(var j = 0; j < array2.length; j++)
{
//you would access the element of the array as array1[i] and array2[j]
//create and array with as many elements as the number of arrays you are to combine
//add them in
//you could have as many dimensions as you need
combos.push(array1[i] + array2[j])
}
}
Assuming you're using a recent web browser with support for Array.forEach:
var combos = [];
array1.forEach(function(a1){
array2.forEach(function(a2){
combos.push(a1 + a2);
});
});
If you don't have forEach, it is an easy enough exercise to rewrite this without it. As others have proven before, there's also some performance advantages to doing without... (Though I contend that not long from now, the common JavaScript runtimes will optimize away any current advantages to doing this otherwise.)
Solution enhancement for #Nitish Narang's answer.
Use reduce in combo with flatMap to support N arrays combination.
const combo = [
["A", "B", "C"],
["1", "2", "3", "4"]
];
console.log(combo.reduce((a, b) => a.flatMap(x => b.map(y => x + y)), ['']))
Here is functional programming ES6 solution:
var array1=["A","B","C"];
var array2=["1","2","3"];
var result = array1.reduce( (a, v) =>
[...a, ...array2.map(x=>v+x)],
[]);
/*---------OR--------------*/
var result1 = array1.reduce( (a, v, i) =>
a.concat(array2.map( w => v + w )),
[]);
/*-------------OR(without arrow function)---------------*/
var result2 = array1.reduce(function(a, v, i) {
a = a.concat(array2.map(function(w){
return v + w
}));
return a;
},[]
);
console.log(result);
console.log(result1);
console.log(result2)
Part II: After my complicated iterative "odometer" solution of July 2018, here's a simpler recursive version of combineArraysRecursively()...
function combineArraysRecursively( array_of_arrays ){
// First, handle some degenerate cases...
if( ! array_of_arrays ){
// Or maybe we should toss an exception...?
return [];
}
if( ! Array.isArray( array_of_arrays ) ){
// Or maybe we should toss an exception...?
return [];
}
if( array_of_arrays.length == 0 ){
return [];
}
for( let i = 0 ; i < array_of_arrays.length; i++ ){
if( ! Array.isArray(array_of_arrays[i]) || array_of_arrays[i].length == 0 ){
// If any of the arrays in array_of_arrays are not arrays or are zero-length array, return an empty array...
return [];
}
}
// Done with degenerate cases...
let outputs = [];
function permute(arrayOfArrays, whichArray=0, output=""){
arrayOfArrays[whichArray].forEach((array_element)=>{
if( whichArray == array_of_arrays.length - 1 ){
// Base case...
outputs.push( output + array_element );
}
else{
// Recursive case...
permute(arrayOfArrays, whichArray+1, output + array_element );
}
});/* forEach() */
}
permute(array_of_arrays);
return outputs;
}/* function combineArraysRecursively() */
const array1 = ["A","B","C"];
const array2 = ["+", "-", "*", "/"];
const array3 = ["1","2"];
console.log("combineArraysRecursively(array1, array2, array3) = ", combineArraysRecursively([array1, array2, array3]) );
Here is another take. Just one function and no recursion.
function allCombinations(arrays) {
const numberOfCombinations = arrays.reduce(
(res, array) => res * array.length,
1
)
const result = Array(numberOfCombinations)
.fill(0)
.map(() => [])
let repeatEachElement
for (let i = 0; i < arrays.length; i++) {
const array = arrays[i]
repeatEachElement = repeatEachElement ?
repeatEachElement / array.length :
numberOfCombinations / array.length
const everyElementRepeatedLength = repeatEachElement * array.length
for (let j = 0; j < numberOfCombinations; j++) {
const index = Math.floor(
(j % everyElementRepeatedLength) / repeatEachElement
)
result[j][i] = array[index]
}
}
return result
}
const result = allCombinations([
['a', 'b', 'c', 'd'],
[1, 2, 3],
[true, false],
])
console.log(result.join('\n'))
Arbitrary number of arrays, arbitrary number of elements.
Sort of using number base theory I guess - the j-th array changes to the next element every time the number of combinations of the j-1 arrays has been exhausted. Calling these arrays 'vectors' here.
let vectorsInstance = [
[1, 2],
[6, 7, 9],
[10, 11],
[1, 5, 8, 17]]
function getCombos(vectors) {
function countComb(vectors) {
let numComb = 1
for (vector of vectors) {
numComb *= vector.length
}
return numComb
}
let allComb = countComb(vectors)
let combos = []
for (let i = 0; i < allComb; i++) {
let thisCombo = []
for (j = 0; j < vectors.length; j++) {
let vector = vectors[j]
let prevComb = countComb(vectors.slice(0, j))
thisCombo.push(vector[Math.floor(i / prevComb) % vector.length])
}
combos.push(thisCombo)
}
return combos
}
console.log(getCombos(vectorsInstance))
While there's already plenty of good answers to get every combination, which is of course the original question, I'd just like to add a solution for pagination. Whenever there's permutations involved, there's the risk of extremely large numbers. Let's say, for whatever reason, we wanted to build an interface where a user could still browse through pages of practically unlimited permutations, e.g. show permutations 750-760 out of one gazillion.
We could do so using an odometer similar to the one in John's solution. Instead of only incrementing our way through the odometer, we also calculate its initial value, similar to how you'd convert for example seconds into a hh:mm:ss clock.
function getPermutations(arrays, startIndex = 0, endIndex) {
if (
!Array.isArray(arrays) ||
arrays.length === 0 ||
arrays.some(array => !Array.isArray(array))
) {
return { start: 0, end: 0, total: 0, permutations: [] };
}
const permutations = [];
const arrayCount = arrays.length;
const arrayLengths = arrays.map(a => a.length);
const maxIndex = arrayLengths.reduce(
(product, arrayLength) => product * arrayLength,
1,
);
if (typeof endIndex !== 'number' || endIndex > maxIndex) {
endIndex = maxIndex;
}
const odometer = Array.from({ length: arrayCount }).fill(0);
for (let i = startIndex; i < endIndex; i++) {
let _i = i; // _i is modified and assigned to odometer indexes
for (let odometerIndex = arrayCount - 1; odometerIndex >= 0; odometerIndex--) {
odometer[odometerIndex] = _i % arrayLengths[odometerIndex];
if (odometer[odometerIndex] > 0 && i > startIndex) {
// Higher order values in existing odometer are still valid
// if we're not hitting 0, since there's been no overflow.
// However, startIndex always needs to follow through the loop
// to assign initial odometer.
break;
}
// Prepare _i for next odometer index by truncating rightmost digit
_i = Math.floor(_i / arrayLengths[odometerIndex]);
}
permutations.push(
odometer.map(
(odometerValue, odometerIndex) => arrays[odometerIndex][odometerValue],
),
);
}
return {
start: startIndex,
end: endIndex,
total: maxIndex,
permutations,
};
}
So for the original question, we'd do
getPermutations([['A', 'B', 'C'], ['1', '2', '3']]);
-->
{
"start": 0,
"end": 9,
"total": 9,
"permutations": [
["A", "1"],
["A", "2"],
["A", "3"],
["B", "1"],
["B", "2"],
["B", "3"],
["C", "1"],
["C", "2"],
["C", "3"]
]
}
but we could also do
getPermutations([['A', 'B', 'C'], ['1', '2', '3']], 2, 5);
-->
{
"start": 2,
"end": 5,
"total": 9,
"permutations": [
["A", "3"],
["B", "1"],
["B", "2"]
]
}
And more importantly, we could do
getPermutations(
[
new Array(1000).fill(0),
new Array(1000).fill(1),
new Array(1000).fill(2),
new Array(1000).fill(3),
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
['X', 'Y', 'Z'],
['1', '2', '3', '4', '5', '6']
],
750,
760
);
-->
{
"start": 750,
"end": 760,
"total": 1800000000000000,
"permutations": [
[0, 1, 2, 3, "e", "B", "Z", "1"],
[0, 1, 2, 3, "e", "B", "Z", "2"],
[0, 1, 2, 3, "e", "B", "Z", "3"],
[0, 1, 2, 3, "e", "B", "Z", "4"],
[0, 1, 2, 3, "e", "B", "Z", "5"],
[0, 1, 2, 3, "e", "B", "Z", "6"],
[0, 1, 2, 3, "e", "C", "X", "1"],
[0, 1, 2, 3, "e", "C", "X", "2"],
[0, 1, 2, 3, "e", "C", "X", "3"],
[0, 1, 2, 3, "e", "C", "X", "4"]
]
}
without the computer hanging.
Here's a short recursive one that takes N arrays.
function permuteArrays(first, next, ...rest) {
if (rest.length) next = permuteArrays(next, ...rest);
return first.flatMap(a => next.map(b => [a, b].flat()));
}
Or with reduce (slight enhancement of Penny Liu's):
function multiply(a, b) {
return a.flatMap(c => b.map(d => [c, d].flat()));
}
[['a', 'b', 'c'], ['+', '-'], [1, 2, 3]].reduce(multiply);
Runnable example:
function permuteArrays(first, next, ...rest) {
if (rest.length) next = permuteArrays(next, ...rest);
return first.flatMap(a => next.map(b => [a, b].flat()));
}
const squish = arr => arr.join('');
console.log(
permuteArrays(['A', 'B', 'C'], ['+', '-', '×', '÷'], [1, 2]).map(squish),
permuteArrays(['a', 'b', 'c'], [1, 2, 3]).map(squish),
permuteArrays([['a', 'foo'], 'b'], [1, 2]).map(squish),
permuteArrays(['a', 'b', 'c'], [1, 2, 3], ['foo', 'bar', 'baz']).map(squish),
)
I had a similar requirement, but I needed get all combinations of the keys of an object so that I could split it into multiple objects. For example, I needed to convert the following;
{ key1: [value1, value2], key2: [value3, value4] }
into the following 4 objects
{ key1: value1, key2: value3 }
{ key1: value1, key2: value4 }
{ key1: value2, key2: value3 }
{ key1: value2, key2: value4 }
I solved this with an entry function splitToMultipleKeys and a recursive function spreadKeys;
function spreadKeys(master, objects) {
const masterKeys = Object.keys(master);
const nextKey = masterKeys.pop();
const nextValue = master[nextKey];
const newObjects = [];
for (const value of nextValue) {
for (const ob of objects) {
const newObject = Object.assign({ [nextKey]: value }, ob);
newObjects.push(newObject);
}
}
if (masterKeys.length === 0) {
return newObjects;
}
const masterClone = Object.assign({}, master);
delete masterClone[nextKey];
return spreadKeys(masterClone, newObjects);
}
export function splitToMultipleKeys(key) {
const objects = [{}];
return spreadKeys(key, objects);
}
one more:
const buildCombinations = (allGroups: string[][]) => {
const indexInArray = new Array(allGroups.length);
indexInArray.fill(0);
let arrayIndex = 0;
const resultArray: string[] = [];
while (allGroups[arrayIndex]) {
let str = "";
allGroups.forEach((g, index) => {
str += g[indexInArray[index]];
});
resultArray.push(str);
// if not last item in array already, switch index to next item in array
if (indexInArray[arrayIndex] < allGroups[arrayIndex].length - 1) {
indexInArray[arrayIndex] += 1;
} else {
// set item index for the next array
indexInArray[arrayIndex] = 0;
arrayIndex += 1;
// exclude arrays with 1 element
while (allGroups[arrayIndex] && allGroups[arrayIndex].length === 1) {
arrayIndex += 1;
}
indexInArray[arrayIndex] = 1;
}
}
return resultArray;
};
One example:
const testArrays = [["a","b"],["c"],["d","e","f"]]
const result = buildCombinations(testArrays)
// -> ["acd","bcd","ace","acf"]
My version of the solution by John D. Aynedjian, which I rewrote for my own understanding.
console.log(getPermutations([["A","B","C"],["1","2","3"]]));
function getPermutations(arrayOfArrays)
{
let permutations=[];
let remainder,permutation;
let permutationCount=1;
let placeValue=1;
let placeValues=new Array(arrayOfArrays.length);
for(let i=arrayOfArrays.length-1;i>=0;i--)
{
placeValues[i]=placeValue;
placeValue*=arrayOfArrays[i].length;
}
permutationCount=placeValue;
for(let i=0;i<permutationCount;i++)
{
remainder=i;
permutation=[];
for(let j=0;j<arrayOfArrays.length;j++)
{
permutation[j]=arrayOfArrays[j][Math.floor(remainder/placeValues[j])];
remainder=remainder%placeValues[j];
}
permutations.push(permutation.reduce((prev,curr)=>prev+curr,"")); }
return permutations;
}
First express arrays as array of arrays:
arrayOfArrays=[["A","B","C"],["a","b","c","d"],["1","2"]];
Next work out the number of permuations in the solution by multiplying the number of elements in each array by each other:
//["A","B","C"].length*["a","b","c","d"].length*["1","2"].length //24 permuations
Then give each array a place value, starting with the last:
//["1","2"] place value 1
//["a","b","c","d"] place value 2 (each one of these letters has 2 possibilities to the right i.e. 1 and 2)
//["A","B","C"] place value 8 (each one of these letters has 8 possibilities to the right i.e. a1,a2,b1,b2,c1,c2,d1,d2
placeValues=[8,2,1]
This allows each element to be represented by a single digit:
arrayOfArrays[0][2]+arrayOfArrays[1][3]+arrayOfArrays[2][0] //"Cc1"
...would be:
2*placeValues[2]+3*placesValues[1]+0*placeValues[2] //2*8+3*2+0*1=22
We actually need to do the reverse of this so convert numbers 0 to the number of permutations to an index of each array using quotients and remainders of the permutation number.
Like so:
//0 = [0,0,0], 1 = [0,0,1], 2 = [0,1,0], 3 = [0,1,1]
for(let i=0;i<permutationCount;i++)
{
remainder=i;
permutation=[];
for(let j=0;j<arrayOfArrays.length;j++)
{
permutation[j]=arrayOfArrays[j][Math.floor(remainder/placeValues[j])];
remainder=remainder%placeValues[j];
}
permutations.push(permutation.join(""));
}
The last bit turns the permutation into a string, as requested.
Make a loop like this
->
let numbers = [1,2,3,4,5];
let letters = ["A","B","C","D","E"];
let combos = [];
for(let i = 0; i < numbers.length; i++) {
combos.push(letters[i] + numbers[i]);
};
But you should make the array of “numbers” and “letters” at the same length thats it!

Categories

Resources