mowwwalker
mowwwalker

Reputation: 17334

Returning an array without a removed element? Using splice() without changing the array?

I want to do something like:

var myArray = ["one","two","three"];
document.write(myArray.splice(1,1));
document.write(myArray);

So that it shows first "one,three", and then "one,two,three". I know splice() returns the removed element and changes the array, but is there function to return a new array with the element removed? I tried:

window.mysplice = function(arr,index,howmany){
    arr.splice(index,howmany);
    return arr;   
};

If I try:

var myArray = ["one","two","three"];
document.write(mySplice(myArray,1,1));
document.write(myArray);

It still changes myArray.

Upvotes: 79

Views: 88501

Answers (16)

Bhargav
Bhargav

Reputation: 121

If you wanted a utility to reuse :

const myArray = ["one", "two", "three", "four", "five"];

const yourSplice = (yourArray, elementToRemove) => {
  const index = yourArray.indexOf(elementToRemove);    
  if (index !== -1) {
    return [...yourArray.slice(0, index), ...yourArray.slice(index+1)];
  } 
  return yourArray;
}

console.log(yourSplice(myArray, "three"));

Upvotes: 0

Nitin Jadhav
Nitin Jadhav

Reputation: 7296

Return new array without mutating original one

JavaScript arrays has a new method for this purpose: array.toSpliced()

const months = ["Jan", "Mar", "Apr", "May"];

//Delete at index 1
const months1 = months.toSpliced(1,1);
console.log(months1); // ["Jan", "Apr", "May"]

// Deleting/Inserting an element at index 1
const months2 = months.toSpliced(1, 0, "Feb");
console.log(months2); // ["Jan", "Feb", "Mar", "Apr", "May"]

//months remain unchanged ["Jan", "Mar", "Apr", "May"]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced

Upvotes: 1

Josh
Josh

Reputation: 2694

There's a new tc39 proposal, which adds a toSpliced method to Array that returns a copy of the array and doesn't modify the original.

When this is implemented, the question can be answered with:

const myArray = ["one", "two", "three"];
myArray.toSpliced(1, 1); // => ["one", "three"]
myArray; // => ["one", "two", "three"];

As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.

Upvotes: 6

mjcl
mjcl

Reputation: 46

If you have the index of the element you want to remove, you can use slice() and spread syntax:

let fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
let removeIndex = 2;
let iHateLemons = [...fruits.slice(0, removeIndex), ...fruits.slice(removeIndex+1)]

// your new array
// console.log(iHateLemons) --> ["Banana", "Orange", "Apple", "Mango"]
// original array still intact
// console.log(fruits) --> ["Banana", "Orange", "Lemon", "Apple", "Mango"]

Upvotes: 3

corysimmons
corysimmons

Reputation: 7675

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const oneTwoThree = ['one', 'two', 'three'] // original array

// `filter()` (like most array functions) iterates over every item in the array.
// Whatever returns true here is copied to a new array (the `oneThree` variable).
// `item !== 'two'` returns true for everything except 'two'
const oneThree = oneTwoThree.filter(item => item !== 'two')

console.log(oneTwoThree) // ['one', 'two', 'three'] — the original, unscathed, array
console.log(oneThree) // ['one', 'three'] — a copy of the original, sans the value you wanted to remove

You'd want to do this so you have a non-mutated array.

I don't think performance is as good as something like slice + concat, but worry about that if it becomes a problem (it probably won't unless you're dealing with tens-of-thousands of elements in an array). Until then, filter is really clean.

Also note that this will remove ALL instances of the element two from the array, so make sure you don't have duplicates in your array that might unintentionally get gobbled up by this approach.

Upvotes: 6

Yorkshireman
Yorkshireman

Reputation: 2343

document.write(myArray.filter(e => e !== "two"));
document.write(myArray);

Upvotes: 0

Rick Su
Rick Su

Reputation: 16440

as suggested by the answer below, here is a code snapshot

var myArray = ["one", "two", "three"];
var cloneArray = myArray.slice();

myArray.splice(1, 1);

console.log(myArray);
console.log(cloneArray);

Upvotes: 59

Ben Carp
Ben Carp

Reputation: 26548

const getSubArr = (arr, start, end) => {
    return end > start
        ? arr.filter((_, i) => i >= start && i < end)
        : arr.filter((_, i) => i >= start || i < end);
};

This function returns an array which is a sequence of the original array. It's advantage is that it could be used to get a subArray without a sequence located in the middle of the original array.

const chars = ["a", "b", "c", "d", "e", "f"];
console.log(getArrInRange(chars, 2, 4));
console.log(getArrInRange(chars, 4, 2));

Upvotes: 0

vdegenne
vdegenne

Reputation: 13270

I think the neatest way is to create a simple function, and bind the function to the Array prototype if you need global access.

Most of the answers provided to the question are wrong. People confuse returning one element of one array without modifying its content but what the OP needs is to return a clone of the array without one element.

Here's my solution :

let arr = ['one', 'two', 'three'];

/* functional */
window.cloneSlice = (arr, start, end) => {
  const _arr = arr.slice();
  _arr.splice(start, end);
  return _arr;
}
// usage
console.log(cloneSlice(arr, 1, 1)); // one, three
console.log(arr); // one, two, three

/* prototyped */
Array.prototype.cloneSlice = function (start, end) { return cloneSlice(this, start, end) }
// usage
console.log(arr.cloneSlice(1, 1)); // one, three
console.log(arr); // one, two, three

Upvotes: 0

Esteban Panelli
Esteban Panelli

Reputation: 320

I think the best approach to splice an element from array without mutating and without making a copy of itself is using filter:

arr = ["one", "two", "three"]
elToRemove = "two"
filteredArr = arr.filter( n => n != elToRemove)

console.log(arr) // ["one", "two", "three"]
console.log(filteredArr) // ["one", "three"]

Upvotes: 2

cgn.dev
cgn.dev

Reputation: 1014

You can use the ES6 spread feature:

let myArray = ['one','two','three'];
let mySplicedArray = [...myArray];
mySplicedArray.splice(1,1); 

console.log(myArray); /// ['one', 'two', 'three']
console.log(mySplicedArray); /// ['one', 'three']

Upvotes: 6

Thai-Duong Nguyen
Thai-Duong Nguyen

Reputation: 291

Use this:

function spliceNoMutate(myArray,indexToRemove) {
    return myArray.slice(0,indexToRemove).concat(myArray.slice(indexToRemove+1));
}

Upvotes: 29

Rafael
Rafael

Reputation: 577

I know this question is old, but this approach might come in handy.

var myArray = ["one","two","three"];
document.write(myArray.filter(function(v, index) { return index !== 1 })

or

var myArray = ["one","two","three"];
document.write(myArray.filter(function(v, index) { return v !== "two" })

This uses the Array.filter() function and tests against either the index being 1 or the value being "two".


Now, I cannot vouch for these solution's performance (as it checks each item on the array, Nguyen's answer might be more efficient), but it is more flexible if you want to do more complicated stuff and sure is easier to understand.

Upvotes: 14

mu is too short
mu is too short

Reputation: 434665

You want slice:

Returns a one-level deep copy of a portion of an array.

So if you

a = ['one', 'two', 'three' ];
b = a.slice(1, 3);

Then a will still be ['one', 'two', 'three'] and b will be ['two', 'three']. Take care with the second argument to slice though, it is one more than the last index that you want to slice out:

Zero-based index at which to end extraction. slice extracts up to but not including end.

Upvotes: 50

SeanCannon
SeanCannon

Reputation: 77966

Why not just reference the index?

var myArray = ["one","two","three"];
document.write(myArray[1] + '<br />');
document.write(myArray);

Example: http://jsfiddle.net/AlienWebguy/dHTUj/

Upvotes: 0

jfriend00
jfriend00

Reputation: 707298

Instead of this:

document.write(myArray.splice(1,1));

why not just use:

document.write(myArray[1]);

splice() modifies the array in place by definition. See slice() if you want a copy.

Upvotes: 0

Related Questions