提问



我有一个整数数组,我使用.push()方法向其中添加元素。


有没有一种简单的方法从数组中删除特定元素?等同于array.remove(int);之类的东西。


我必须使用 core JavaScript - no 框架是允许的。

最佳参考


找到要删除的数组元素的index,然后用splice删除该索引。[112]



  splice()方法通过删除来更改数组的内容
  现有元素和/或添加新元素。



var array = [2, 5, 9];
var index = array.indexOf(5);
if (index > -1) {
  array.splice(index, 1);
}
// array = [2, 9]


splice的第二个参数是要删除的元素数。请注意splice修改数组并返回一个包含已删除元素的新数组。





注意:对indexOf的浏览器支持有限; Internet和Explorer 7和8不支持它。[113]


如果您在不受支持的浏览器中需要indexOf,请尝试以下polyfill。在此处 polyfill 了解更多信息。[114]


Array.prototype.indexOf || (Array.prototype.indexOf = function(d, e) {
    var a;
    if (null == this) throw new TypeError('"this" is null or not defined');
    var c = Object(this),
        b = c.length >>> 0;
    if (0 === b) return -1;
    a = +e || 0;
    Infinity === Math.abs(a) && (a = 0);
    if (a >= b) return -1;
    for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {
        if (a in c && c[a] === d) return a;
        a++
    }
    return -1
});

其它参考1


我不知道你期待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];

其它参考2


于2016年10月编辑




  • 简单,直观,明确(https://en.wikipedia.org/wiki/Occam%27s_razor)

  • 不可变(原始数组保持不变)

  • 使用标准JS功能,如果您的浏览器不支持它们 - 使用polyfill



在这个代码示例中,我使用array.filter(...)函数从数组中删除不需要的项目,此函数不会更改原始数组并创建一个新数组。如果您的浏览器没有t支持此功能(例如版本9之前的IE或版本1.5之前的Firefox),请考虑使用来自Mozilla的过滤器polyfill [115] [116]


删除项目(ECMA-262 Edition 5 code aka oldstyle JS)



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 ]


删除项目(ES2015代码)



let value = 3

let arr = [1, 2, 3, 4, 5, 3]

arr = arr.filter(item => item !== value)

console.log(arr)
// [ 1, 2, 4, 5 ]


重要 ES2015()=> {}IE根本不支持箭头功能语法,Chrome版本为45版本,Firefox版本为22版本,Safari版本为10版本。要在旧浏览器中使用ES2015语法,您可以使用BabelJS [117]





删除多个项目(ES2016代码)



此方法的另一个优点是您可以删除多个项目


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(...)功能根本不支持IE浏览器,Chrome之前的47版本,Firefox之前的43版本,Safari之前的9版本以及Edge之前的14版本这里是来自Mozilla的polyfill [118]


删除多个项目(尖端实验性JavaScript ES2018?)



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


在BabelJS中亲自尝试:) [119]


参考



  • Array.prototype.includes

  • 此绑定语法提案

  • 功能组合


其它参考3


取决于你是否想保留一个空位。[120] [121] [122]


如果你想要一个空插槽,删除就可以了:


delete array[ index ];


如果你不这样做,你应该使用拼接方法:[123]


array.splice( index, 1 );


如果你需要该项的值,你可以只存储返回的数组的元素:


var value = array.splice( index, 1 )[0];


如果你想按某种顺序进行,你可以使用array.pop()作为最后一个,或者array.shift()作为第一个(并且两者都返回项目的值)。


如果您不知道该项目的索引,您可以使用array.indexOf( item )来获取它(在if()中获取一个项目或在while()中获取所有项目) 。array.indexOf( item )返回索引,如果找不到则返回-1。 

其它参考4


一位朋友在互联网上遇到问题   8,并告诉我他做了什么。我告诉他这是错的,他告诉我他在这里得到了答案。当前的最佳答案不适用于所有浏览器(例如Internet  Explorer  8),它只会删除第一次出现的项目。[124]


从数组中删除所有实例



function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}


它向后循环遍历数组(因为索引和长度将随着项目的移除而改变)并且如果找到则删除该项目。它适用于所有浏览器。

其它参考5


有两种主要方法:



  1. splice():anArray.splice(index, 1);

  2. 删除:delete anArray[index];



对数组使用delete时要小心。删除对象的属性很好,但对数组不太好。最好将splice用于数组。


请记住,当您使用delete作为数组时,anArray.length可能会得到错误的结果。换句话说,delete将删除元素,但不会更新length属性的值。


使用删除后,您还可能会在索引号中出现漏洞,例如:你可能最终得到索引1,3,4,8,9,11和使用删除之前的长度。
在这种情况下,所有索引for循环都会崩溃,因为索引不再是顺序的。


如果由于某种原因被迫使用delete,那么当需要循环遍历数组时,应该使用for each循环。事实上,如果可能的话,总是避免使用索引for循环。这样代码就会更健壮,更不容易出现索引问题。

其它参考6


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)



无需使用indexOfsplice。但是,如果您只想删除一个元素,它会表现得更好。


查找并移动(移动):


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;
}


使用indexOfsplice(indexof):


function indexof(arr, val) {
  var i;
  while ((i = arr.indexOf(val)) != -1) {
    arr.splice(i, 1);
  }
}


仅使用splice(拼接):


function splice(arr, val) {
  for (var i = arr.length; i--;) {
    if (arr[i] === val) {
      arr.splice(i, 1);
    }
  }
}


具有1000个元素(平均超过10000次运行)的数组的nodejs的运行时间:


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

其它参考7


太老了回复,但可能通过提供谓词而不是值来帮助某人。


注意:它将更新给定的数组,并返回受影响的行


用法



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;
    }
};

其它参考8


John Resig发布了一个很好的实现:[126]


// 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元素阵列。不知道为什么,但我确认约翰的原始实施没有这个问题。

其它参考9


Underscore.js可用于解决多个浏览器的问题。它使用内置浏览器方法(如果存在)。如果他们缺席,就像旧版Internet Explorer版本一样,它会使用自己的自定义方法。[127]


从数组中删除元素的简单示例(来自网站):


_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]

其它参考10


您可以使用过滤方法轻松完成:[128]


function remove(arrOriginal, elementToRemove){
    return arrOriginal.filter(function(el){return el !== elementToRemove});
}
console.log( remove([1, 2, 1, 0, 3, 1, 4], 1) );


这将从数组中删除所有元素,并且比slice和indexOf的组合更快地工作

其它参考11


如果要删除已删除位置的新数组,可以始终删除特定元素并过滤掉数组。它可能需要为不实现过滤方法的浏览器扩展数组对象,但从长远来看它更容易,因为你所做的就是:[129]


var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';}));


应显示[1, 2, 3, 4, 6]

其它参考12


您可以使用ES6。


var array=['1','2','3','4','5','6']
var index = array.filter((value)=>value!='3');


输出:


["1", "2", "4", "5", "6"]

其它参考13


看看这段代码。它适用于每个主要浏览器


remove_item = function (arr, value) {
    var b = '';
    for (b in arr) {
        if (arr[b] === value) {
            arr.splice(b, 1);
            break;
        }
    }
    return arr;
}


调用此功能


remove_item(array,value);

其它参考14


你可以使用lodash _.pull(变异数组),_。pullAt(变异数组)或_.without(确实是t变异数组),[130] [131] [132]


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

其它参考15


我对JavaScript很新,需要这个功能。我只写了这个:


function removeFromArray(array, item, index) {
  while((index = array.indexOf(item)) > -1) {
    array.splice(index, 1);
  }
}


然后,当我想使用它时:


//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");


输出 - 正如所料。
[[item1,item1]]


您可能有不同的需求,因此您可以轻松修改它以适应它们。我希望这可以帮助别人。

其它参考16


好的,例如,你有以下数组:


var num = [1, 2, 3, 4, 5];


我们想删除4号,你可以简单地做下面的代码:


num.splice(num.indexOf(4), 1); //num will be [1, 2, 3, 5];


如果重新使用此函数,则编写一个可重用的函数,该函数将附加到Native数组函数,如下所示:


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];
}


但是,如果您使用下面的数组而不是数组中的
delete array[i];
s,那怎么样?


var num = [5, 6, 5, 4, 5, 1, 5];


我们需要一个循环来检查所有这些,但更容易和更有效的方法是使用内置的JavaScript函数,所以我们编写一个使用过滤器的函数,如下所示:


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]


还有第三方库可以帮助你做这些,比如Lodash或Underscore,有关更多信息,请查看lodash _.pull,_.pullAt或_.without。

其它参考17


ES6&没有变异:( 2016年10月)



const removeByIndex = (list, index) =>
  [
    ...list.slice(0, index),
    ...list.slice(index + 1)
  ];


然后 :


removeByIndex([33,22,11,44],1) //=> [33,11,44]

其它参考18


如果阵列中有复杂对象,可以使用过滤器吗?
在$ .inArray或array.splice不那么容易使用的情况下。特别是如果对象在数组中可能很浅。


例如。如果您有一个带有Id字段的对象,并且您希望从数组中删除该对象:


this.array = this.array.filter(function(element, i) {
    return element.id !== idToRemove;
});

其它参考19


更新:仅当您无法使用ECMAScript 2015(以前称为ES6)时,才推荐使用此方法。如果你可以使用它,这里的其他答案提供了更简洁的实现。





这里的要点将解决您的问题,并删除所有出现的参数而不只是1(或指定的值)。[133]


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;
}


用法:


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]

其它参考20


一个更现代的ECMAScript 2015(以前称为Harmony或ES  6)方法。鉴于:[134]


const items = [1, 2, 3, 4];
const index = 2;


然后:


items.filter((x, i) => i !== index);


产量:


[1, 2, 4]


您可以使用Babel和polyfill服务来确保跨浏览器能够很好地支持它。[135] [136]

其它参考21


你永远不应该在你的数组中改变你的数组。因为这是针对功能编程模式的。你可以做的是创建一个新的数组,而不引用你想要使用es6方法改变数据的数组filter;


var myArray = [1,2,3,4,5,6];


假设你要从数组中删除5,你就可以这样做。


myArray = myArray.filter(value => value !== 5);


这将为您提供一个没有您想要删除的值的新数组。结果将是


 [1,2,3,4,6]; // 5 has been removed from this array


为了进一步理解,您可以阅读有关Array.filter的MDN文档https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter[137]

其它参考22


我知道已有很多答案,但其中许多似乎使问题复杂化。这是一种简单的,递归的方式来删除键的所有实例 - 调用self直到找不到索引。是的,它只适用于indexOf的浏览器,但它很简单,可以很容易地填充。


独立功能


function removeAll(array, key){
    var index = array.indexOf(key);

    if(index === -1) return;

    array.splice(index, 1);
    removeAll(array,key);
}


原型方法


Array.prototype.removeAll = function(key){
    var index = this.indexOf(key);

    if(index === -1) return;

    this.splice(index, 1);
    this.removeAll(key);
}

其它参考23


如果元素有多个实例,则可以执行向后循环以确保不会搞砸索引。


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);
}


现场演示


其它参考24


以下是使用JavaScript 从数组中删除项目的几种方法[138]


描述的所有方法都不会改变原始数组,而是创建一个新数组。


如果您知道项目的索引



假设您有一个数组,并且想要删除位置i中的项目。


一种方法是使用slice():




const items = ['a', 'b', 'c', 'd', 'e', 'f']
const i = 3
const filteredItems = items.slice(0, i-1).concat(items.slice(i, items.length))

console.log(filteredItems)



  Array.prototype.removeItem = function(a) {
            for (i = 0; i < this.length; i++) {
                if (this[i] == a) {
                    for (i2 = i; i2 < this.length - 1; i2++) {
                        this[i2] = this[i2 + 1];
                    }
                    this.length = this.length - 1
                    return;
                }
            }
        }

    var recentMovies = ['Iron Man', 'Batman', 'Superman', 'Spiderman'];
    recentMovies.removeItem('Superman');

其它参考25


按索引删除


返回没有索引元素的数组副本的函数。


/**
* removeByIndex
* @param {Array} array
* @param {Number} index
*/
function removeByIndex(array, index){
    return array.filter(function(elem, _index){
        return index != _index;
    });
}
l = [1,3,4,5,6,7];
console.log(removeByIndex(l, 1));

$> [ 1, 4, 5, 6, 7 ]


按值删除


返回没有Value的数组副本的函数。


/**
* removeByValue
* @param {Array} array
* @param {Number} value
*/
function removeByValue(array, value){
    return array.filter(function(elem, _index){
        return value != elem;
    });
}
l = [1,3,4,5,6,7];
console.log(removeByValue(l, 5));

$> [ 1, 3, 4, 6, 7]

其它参考26


基于所有主要正确的答案并考虑到建议的最佳实践(特别是不直接使用Array.prototype),我想出了以下代码:


function arrayWithout(arr, values) {
  var isArray = function(canBeArray) {
    if (Array.isArray) {
      return Array.isArray(canBeArray);
    }
    return Object.prototype.toString.call(canBeArray) === '[object Array]';
  };

  var excludedValues = (isArray(values)) ? values : [].slice.call(arguments, 1);
  var arrCopy = arr.slice(0);

  for (var i = arrCopy.length - 1; i >= 0; i--) {
    if (excludedValues.indexOf(arrCopy[i]) > -1) {
      arrCopy.splice(i, 1);
    }
  }

  return arrCopy;
}


回顾上述功能,尽管它工作正常,但我意识到可能会有一些性能提升。使用ES6而不是ES5也是一种更好的方法。为此,这是改进的代码:


const arrayWithoutFastest = (() => {
  const isArray = canBeArray => ('isArray' in Array) 
    ? Array.isArray(canBeArray) 
    : Object.prototype.toString.call(canBeArray) === '[object Array]';

  let mapIncludes = (map, key) => map.has(key);
  let objectIncludes = (obj, key) => key in obj;
  let includes;

  function arrayWithoutFastest(arr, ...thisArgs) {
    let withoutValues = isArray(thisArgs[0]) ? thisArgs[0] : thisArgs;

    if (typeof Map !== 'undefined') {
      withoutValues = withoutValues.reduce((map, value) => map.set(value, value), new Map());
      includes = mapIncludes;
    } else {
      withoutValues = withoutValues.reduce((map, value) => { map[value] = value; return map; } , {}); 
      includes = objectIncludes;
    }

    const arrCopy = [];
    const length = arr.length;

    for (let i = 0; i < length; i++) {
      // If value is not in exclude list
      if (!includes(withoutValues, arr[i])) {
        arrCopy.push(arr[i]);
      }
    }

    return arrCopy;
  }

  return arrayWithoutFastest;  
})();


如何使用:


const arr = [1,2,3,4,5,"name", false];

arrayWithoutFastest(arr, 1); // will return array [2,3,4,5,"name", false]
arrayWithoutFastest(arr, 'name'); // will return [2,3,4,5, false]
arrayWithoutFastest(arr, false); // will return [2,3,4,5]
arrayWithoutFastest(arr,[1,2]); // will return [3,4,5,"name", false];
arrayWithoutFastest(arr, {bar: "foo"}); // will return the same array (new copy)


我目前正在撰写一篇博文,其中我对Array的几个解决方案进行了基准测试,没有遇到任何问题,并比较了运行所需的时间。完成该帖后,我将使用链接更新此答案。只是为了让你知道,我已经将上面的内容与lodash的内容进行了比较,如果浏览器不支持Map,它会打败lodash!注意我没有使用Array.prototype.indexOfArray.prototype.includes将exlcudeValues包装在MapObject中可以更快地查询!(https://jsperf.com/array-without-benchmark-against-lodash)[139]

其它参考27


创建新阵列


var my_array = new Array();


向此阵列添加元素:


my_array.push("element1");


函数indexOf(返回索引或未找到时为-1):


var indexOf = function(needle) 
{
    if(typeof Array.prototype.indexOf === 'function') // newer browsers
    {
        indexOf = Array.prototype.indexOf;
    } 
    else // older browsers
    {
        indexOf = function(needle) 
        {
            var index = -1;

            for(var i = 0; i < this.length; i++) 
            {
                if(this[i] === needle) 
                {
                    index = i;
                    break;
                }
            }
            return index;
        };
    }

    return indexOf.call(this, needle);
};


检查此元素的索引(使用firefox和IE8 +测试):


var index = indexOf.call(my_array, "element1");


从阵列中删除位于索引处的1个元素


my_array.splice(index, 1);