返回一个没有移除元素的数组? 使用 splice()而不改变数组?

我想这样做:

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

所以它首先显示“一,三”,然后是“一,二,三”。我知道 splice ()返回删除的元素并更改数组,但是否有函数返回删除元素后的新数组?我试过:

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

如果我尝试:

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

它仍然改变我的数组。

70441 次浏览

你想要 slice:

返回数组部分的一级深拷贝。

所以如果你

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

那么 a仍然是 ['one', 'two', 'three']b仍然是 ['two', 'three']。不过,要注意 slice的第二个参数,它比你想要剔除的最后一个索引多一个:

从零开始的索引,最终提取。 slice提取到但不包括 end

而不是这样:

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

为什么不用:

document.write(myArray[1]);

splice()根据定义修改数组。如果需要副本,请参见 slice()

为什么不直接引用索引呢?

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

例子: http://jsfiddle.net/AlienWebguy/dHTUj/

正如下面的答案所示,这里是一个代码快照

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


myArray.splice(1, 1);


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

用这个:

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

我知道这个问题很老了,但这种方法可能会派上用场。

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

或者

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

这将使用 Array.filter()函数,并根据索引为1或值为“2”进行测试。


现在,我不能保证这些解决方案的性能(因为它检查数组中的每个条目,Nguyen 的 回答可能更有效率) ,但是如果你想做更复杂的事情,它更灵活,当然也更容易理解。

你可以使用 ES6的扩展功能:

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


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

我认为最好的方法是使用 filter:

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


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

我认为最简单的方法是创建一个简单的函数,如果需要全局访问,则将该函数绑定到 Array 原型。

这个问题的大多数答案都是错误的。人们在不修改数组内容的情况下返回数组的一个元素,但 OP 需要的是返回一个没有一个元素的数组克隆。

我的解决办法是:

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

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

此函数返回一个数组,该数组是原始数组的序列。它的优点在于,它可以用来获得子数组,而不需要在原始数组的中间添加序列。

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

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

这样就有了一个 没有变异数组。

我认为性能不如 slice + concat这样的东西好,但是如果它成为一个问题就要担心了(除非你处理的是数组中成千上万个元素,否则很可能不会出现问题)。在此之前,filter是非常干净的。

还要注意的是,这将从数组中删除元素 two的所有实例,所以要确保数组中没有重复的实例,否则这种方法可能会无意中占用这些实例。

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

如果有要删除的元素的索引,可以使用 slice ()和传播语法:

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"]

有一个新的 Tc39建议书,它向 Array添加一个 toSpliced方法,返回数组的一个副本,并且不修改原始数组。

实施后,问题可以通过以下方式得到解答:

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

由于它目前处于第三阶段,它很可能很快就会在浏览器引擎中实现,但与此同时,一个填充物是可用的 给你core-js