我有一个数字数组,并且正在使用.push()
方法向其中添加元素。
有没有一种简单的方法可以从数组中删除特定元素?等价于array.remove(number);
。
我必须使用核心 JavaScript - 不允许使用框架。
使用indexOf
查找要删除的数组元素的index
,然后使用splice
删除该索引。
splice()方法通过删除现有元素和 / 或添加新元素来更改数组的内容。
const array = [2, 5, 9];
console.log(array);
const index = array.indexOf(5);
if (index > -1) {
array.splice(index, 1);
}
// array = [2, 9]
console.log(array);
splice
的第二个参数是要删除的元素数。请注意, splice
会在适当位置修改数组,并返回一个包含已删除元素的新数组。
我不知道您期望array.remove(int)
表现如何。我可以想到您可能想要的三种可能性。
要删除索引i
处的数组元素:
array.splice(i, 1);
如果要从数组中删除每个具有值number
元素:
for(var i = array.length - 1; i >= 0; i--) {
if(array[i] === number) {
array.splice(i, 1);
}
}
如果只想使索引i
处的元素不再存在,但又不想更改其他元素的索引:
delete array[i];
在此代码示例中,我使用“array.filter(...)”函数从数组中删除不需要的项。此函数不会更改原始数组,而是创建一个新数组。如果您的浏览器不支持此功能(例如,版本 9 之前的 Internet Explorer 或版本 1.5 之前的 Firefox),请考虑使用Mozilla 中的过滤器 polyfill 。
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 ]
let value = 3
let arr = [1, 2, 3, 4, 5, 3]
arr = arr.filter(item => item !== value)
console.log(arr)
// [ 1, 2, 4, 5 ]
重要说明 ECMAScript 6 的箭头函数语法完全不支持 Internet Explorer,45 之前的 Chrome,22 之前的 Firefox 和 10 之前的 Safari。要在旧的浏览器中使用 ECMAScript 6 语法,可以使用BabelJS 。
此方法的另一个优点是您可以删除多个项目
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 ]
重要提示 “array.includes(...)” 功能在 Internet Explorer,47 之前的 Chrome,43 之前的 Firefox,9 之前的 Safari 和 14 之前的 Edge 中完全不支持,因此这里是 Mozilla 的 polyfill 。
如果“此绑定语法”提议曾经被接受,则可以执行以下操作:
// 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 ]
参考
这取决于您是否要保留空白点。
如果您确实想要一个空插槽,则可以删除:
delete array[index];
如果不这样做,则应使用splice方法:
array.splice(index, 1);
而且,如果您需要该项目的值,则可以只存储返回的数组的元素:
var value = array.splice(index, 1)[0];
如果您想按某种顺序进行操作,则可以将array.pop()
用于最后一个,或者将array.shift()
用于第一个(并且两者也都返回该项的值)。
而且,如果您不知道该项目的索引,则可以使用array.indexOf(item)
来获取它(在if()
中获取一个项目, while()
在while()
中获取所有它们)。 array.indexOf(item)
返回索引,如果未找到则返回 - 1。
一个朋友在Internet Explorer 8 中遇到问题,向我展示了他的工作。我告诉他这是错误的,他告诉我他在这里得到了答案。当前的最佳答案不能在所有浏览器(例如 Internet Explorer 8)中都起作用,并且只会删除该项目的第一个匹配项。
function remove(arr, item) {
for (var i = arr.length; i--;) {
if (arr[i] === item) {
arr.splice(i, 1);
}
}
}
它向后循环遍历数组(因为索引和长度会随着项目的删除而改变),并在找到后删除该项目。它适用于所有浏览器。
有两种主要方法:
splice() : anArray.splice(index, 1);
delete : delete anArray[index];
对数组使用 delete 时要小心。这对删除对象的属性很有用,但对数组却不太好。最好对数组使用splice
。
请记住,当对数组使用delete
时, anArray.length
可能会得到错误的结果。换句话说, delete
会删除元素,但不会更新 length 属性的值。
您还可以期望在使用 delete 后索引号中出现空洞,例如,最终可能会具有使用 delete 之前的索引 1、3、4、8、9 和 11,以及长度。在这种情况下,所有索引的for
循环都会崩溃,因为索引不再是顺序的。
如果由于某种原因而被迫使用delete
,那么当您需要遍历数组时,应for each
循环使用delete
。实际上,如果可能,请始终避免使用索引for
循环。这样,代码将更健壮,并且不易出现索引问题。
Array.prototype.remByVal = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
//Call like
[1, 2, 3, 4].remByVal(3);
Array.prototype.remByVal = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
}
var rooms = ['hello', 'something']
rooms = rooms.remByVal('hello')
console.log(rooms)
无需使用indexOf
或splice
。但是,如果只想删除一个元素,它的性能会更好。
查找并移动(移动):
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;
}
使用indexOf
和splice
(indexof):
function indexof(arr, val) {
var i;
while ((i = arr.indexOf(val)) != -1) {
arr.splice(i, 1);
}
}
仅使用splice
(splice):
function splice(arr, val) {
for (var i = arr.length; i--;) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
}
在具有 1000 个元素的数组的 nodejs 上的运行时(平均运行 10000 次以上):
indexof大约比move慢 10 倍。即使通过删除对splice 中的 indexOf
的调用进行了改进,它的性能也比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
这提供了谓词而不是值。
注意:它将更新给定的数组,并返回受影响的行。
var removed = helper.removeOne(arr, row => row.id === 5 );
var removed = helper.remove(arr, row => row.name.startsWith('BMW'));
var helper = {
// Remove and return the first occurrence
removeOne: 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
remove: 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;
}
};
John Resig 发布了一个很好的实现 :
// 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);
};
如果您不想扩展全局对象,则可以执行以下操作:
// 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);
};
但是,我发布此消息的主要原因是为了警告用户不要该页面的评论(2007 年 12 月 14 日)中建议的替代实现:
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;
};
一开始它似乎运行良好,但是经过一个痛苦的过程,我发现当尝试删除数组中倒数第二个元素时它失败了。例如,如果您有一个包含 10 个元素的数组,并尝试使用此元素删除第 9 个元素:
myArray.remove(8);
您最终得到一个 8 元素数组。不知道为什么,但是我确认 John 的原始实现没有这个问题。