如何按值从数组中删除项?

Mac*_*Mac 838 javascript arrays

有没有从JavaScript数组中删除项的方法?

给定一个数组:

var ary = ['three', 'seven', 'eleven'];
Run Code Online (Sandbox Code Playgroud)

我想做的事情如下:

removeItem('seven', ary);
Run Code Online (Sandbox Code Playgroud)

我已经调查了splice()但只能通过位置编号删除,而我需要通过其值删除项目.

SLa*_*aks 1430

你可以使用这样的indexOf方法:

var index = array.indexOf(item);
if (index !== -1) array.splice(index, 1);
Run Code Online (Sandbox Code Playgroud)

注意:您需要为IE8及以下版本填充它

var array = [1,2,3,4]
var item = 3

var index = array.indexOf(item);
if (index !== -1) array.splice(index, 1);

console.log(array)
Run Code Online (Sandbox Code Playgroud)

  • 并且当索引不是"-1"时循环它 (67认同)
  • 确保索引!==( - 1),即项目存在于数组中,否则你将拼出数组中的最后一个元素. (33认同)
  • 如果你使用jquery,你可以使用`$ .inArray`而不是`indexOf`,这是跨浏览器兼容的. (31认同)
  • 最好做一个检查,只有拼接,如果不同于"-1",有数百万的选项,明智地选择http://jsperf.com/not-vs-gt-vs-ge/4 (8认同)
  • 查看http://stackoverflow.com/questions/5767325/remove-specific-element-from-an-array (3认同)

ken*_*bec 455

如果不允许添加到本机原型,则可以是全局函数或自定义对象的方法.它会从数组中删除与任何参数匹配的所有项.

Array.prototype.remove = function() {
    var what, a = arguments, L = a.length, ax;
    while (L && this.length) {
        what = a[--L];
        while ((ax = this.indexOf(what)) !== -1) {
            this.splice(ax, 1);
        }
    }
    return this;
};

var ary = ['three', 'seven', 'eleven'];

ary.remove('seven');

/*  returned value: (Array)
three,eleven
*/
Run Code Online (Sandbox Code Playgroud)

使其成为全球 -

function removeA(arr) {
    var what, a = arguments, L = a.length, ax;
    while (L > 1 && arr.length) {
        what = a[--L];
        while ((ax= arr.indexOf(what)) !== -1) {
            arr.splice(ax, 1);
        }
    }
    return arr;
}
var ary = ['three', 'seven', 'eleven'];
removeA(ary, 'seven');


/*  returned value: (Array)
three,eleven
*/
Run Code Online (Sandbox Code Playgroud)

并照顾IE8及以下 -

if(!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(what, i) {
        i = i || 0;
        var L = this.length;
        while (i < L) {
            if(this[i] === what) return i;
            ++i;
        }
        return -1;
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 永远不要改变Array原型.有趣的事情开始发生. (136认同)
  • @madeinstefano,会发生一些或两个有趣(糟糕)事情的例子吗? (23认同)
  • 为什么人们会显示添加到数组原型的示例?堆栈溢出用于学习良好实践 (15认同)
  • @YonnTrimoreau和什么?定义一个不可枚举的属性`Object.defineProperty(Array.prototype,"remove",{enumerable:false});` (6认同)
  • @xorinzor不,.prototype属性是跨浏览器的. (3认同)
  • 直接破解原生对象的原型在JavaScript中很少是一个聪明的主意.您可能会产生不可预测的问题.如果另一个框架试图通过键迭代数组,则您的函数将是输出值之一.在阵列的情况下这不是很酷.如果您想修改Array原型,请遵循@naXa的建议并使用Object.defineProperty.请注意,这将牺牲<= IE8支持.无法填充Object.defineProperty,因为它是一种低级语言功能. (3认同)
  • @YoYoYonnY你缺少所有的JS框架......他们在某些时候都使用`for(var key in arr){}`.我在谈论jQuery,AngularJS ......一些最大的. (2认同)
  • @YoYoYonnY 想象一下 JS 世界,每个人都认为更改原型对于某些随机函数是可以的。如果你改变原型,其他库改变它,所有其他依赖项也改变(现在有数十个依赖项是正常的,所以 2 个库改变功能的机会增加),那么你最终会弄乱一些东西,你或者你不幸的同事会经历了发现问题以来最糟糕的日子。虽然您的评论已有 2 年历史,但我希望您已经对原型有了更多了解,了解它会变得多么棘手、如何使用以及何时可以更改。 (2认同)
  • @LukasLiesis 所以你显然不理解我的评论。我的全部观点是,只要您不必与其他代码交互,或者您知道这些交互是安全的,您就可以使用原型、宏和递归做任何您想做的事情。您认为依赖项可能会使用“原型”更改和破坏现有代码的观点对此没有任何帮助。事实上,我确实知道关于原型以及预处理器、递归、链接列表等的知识,这让我很恼火,有人声称你永远不应该仅仅因为可以使用它们而使用它们错。 (2认同)
  • @LukasLiesis此外,我合法地发现那些拒绝使用`prototype`,预处理器,LinkedLists等等的人,只是因为互联网上的人,通常是StackOverflow,告诉他们他们不应该使用它们.事实并非如此.存在"良好实践",并且存在虚假信息,并且像"原型"这样的陈述永远不应该用于现有对象"根本不是好的做法.MDN很乐意为`Array.prototype`中的几个函数定义polyfill.其中一些将打破写得不好的现有代码.但MDN并没有错,而程序员也是如此. (2认同)

Joh*_*ams 377

单行将会这样做,

var ary = ['three', 'seven', 'eleven'];

// Remove item 'seven' from array
var filteredAry = ary.filter(function(e) { return e !== 'seven' })
//=> ["three", "eleven"]

// In ECMA6 (arrow function syntax):
var filteredAry = ary.filter(e => e !== 'seven')
Run Code Online (Sandbox Code Playgroud)

这使用了JS 中的过滤器功能.IE9及以上版本支持它.

它的作用(来自doc链接)

filter()为数组中的每个元素调用一次提供的回调函数,并构造一个包含所有值的新数组,其中回调返回一个强制为true的值.仅为已分配值的数组的索引调用回调; 对于已删除的索引或从未分配过值的索引,不会调用它.不会通过回调测试的数组元素被简单地跳过,并且不包含在新数组中.

所以基本上,这与所有其他for (var key in ary) { ... }解决方案相同,只是for in从IE6开始支持该构造.

基本上,过滤器是一种方便的方法,与for in构造(AFAIK)相比,看起来更好(并且是可链接的).

  • 请注意,这应该用作`array = array.filter()`,而不仅仅是`array.filter()`. (8认同)
  • 更新@JeffreyRoosendaal贡献的答案(`filter()不会改变调用它的数组.来自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/过滤器). (6认同)
  • 想知道这个精彩的单线并没有得到更多的爱.+1没有循环.通过使用"&&"作为值,可以添加他想要删除的值. (5认同)
  • 请注意,此解决方案会删除数组中值为“7”的所有元素,而不仅仅是像得票最高的答案那样删除第一个元素 (2认同)

vat*_*sal 132

你可以使用underscore.js.这真的让事情变得简单.

例如,有了这个:

var result = _.without(['three','seven','eleven'], 'seven');
Run Code Online (Sandbox Code Playgroud)

而且result['three','eleven'].

在您的情况下,您必须编写的代码是:

ary = _.without(ary, 'seven')
Run Code Online (Sandbox Code Playgroud)

它减少了你编写的代码.

  • 我从来没说过不要在其他地方使用图书馆.如果代码看起来更干净,那么我不介意包括库.为什么人们使用jquery,为什么不使用原始的javascript呢? (15认同)
  • 嗨Kelvin我完全同意你的看法.一个人发表了评论,后来他将其删除,他说使用像下划线这样的库并不酷,我们不应该接受这样的答案.我试图回答它. (11认同)
  • @vatsal - 因为库开发人员可以集中精力使他们的库函数背后的函数快速,简洁和跨浏览器,同时我专注于我的应用程序及其目的.它节省了我的思考时间,因此我有更多的时间来使应用程序更好,而不用担心构成我的应用程序的小功能.有人已经发明了轮子,为什么有人会在每次制造汽车时重新制作它? (10认同)

gad*_*lol 50

看看这个方式:

for(var i in array){
    if(array[i]=='seven'){
        array.splice(i,1);
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在一个功能:

function removeItem(array, item){
    for(var i in array){
        if(array[i]==item){
            array.splice(i,1);
            break;
        }
    }
}

removeItem(array, 'seven');
Run Code Online (Sandbox Code Playgroud)

  • 请记住,如果您将此代码修改为不"中断"并继续循环以删除多个项目,则需要在拼接后立即重新计算i变量,如下所示:i--.那是因为你只是缩小了数组,否则你最终会跳过一个元素. (14认同)
  • 要添加到我上面的注释中,代码将是:for(var i = 0; i <array.length; i ++){/*etc*.*/array.splice(i,1); 一世 - ; (3认同)

Ame*_*icA 36

您可以通过以下两种方式实现:

var arr = ["1","2","3","4"] // we wanna delete number "3"
Run Code Online (Sandbox Code Playgroud)

第一:

arr.indexOf('3') !== -1 && arr.splice(arr.indexOf('3'), 1)
Run Code Online (Sandbox Code Playgroud)

第二(ES6):

arr = arr.filter(e => e !== '3')
Run Code Online (Sandbox Code Playgroud)

  • 如果数组中不存在元素,例如`a.indexOf('3')=== -1`,该怎么办?它会以某种奇怪的方式改变数组(不正确的行为)还是根本不会做任何事情(正确的行为)? (3认同)
  • 如果第一个方法中不存在该项,则会删除列表中的最后一项 (2认同)

Chi*_*aro 36

您可以创建自己的方法,传递数组和要删除的值:

function removeItem(arr, item){
 return arr.filter(f => f !== item)
}
Run Code Online (Sandbox Code Playgroud)

然后你可以调用它:

ary = removeItem(ary, 'seven');
Run Code Online (Sandbox Code Playgroud)


Cor*_*han 35

这是一个使用jQuery的inArray函数的版本:

var index = $.inArray(item, array);
if (index != -1) {
    array.splice(index, 1);
}
Run Code Online (Sandbox Code Playgroud)

  • Splice支持从最后获取的负索引,因此如果找不到该项,则此代码将从数组中删除最后一项. (18认同)
  • @ dman2306嗯,直到现在才看到你的评论,但这是一个非常好的观点.修复了该问题. (2认同)

Kld*_*Kld 28

var index = array.indexOf('item');

if(index!=-1){

   array.splice(index, 1);
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*jra 18

只是

var ary = ['three', 'seven', 'eleven'];
var index = ary.indexOf('seven'); // get index if value found otherwise -1

 if (index > -1) { //if found
   ary.splice(index, 1);
 }
Run Code Online (Sandbox Code Playgroud)

  • 感谢您提供此代码段,该代码段可能会提供一些有限的即时帮助.[正确的解释将大大改善其长期价值](// meta.stackexchange.com/q/114762/206345)通过显示_why_这是一个很好的解决方案,并将使其对未来的读者更有用其他类似的问题.请[编辑]你的答案,添加一些解释,包括你所做的假设. (2认同)
  • 在我的情况下效果最好,因为我想从数组中删除,并将值(要删除)存储到变量中。谢谢! (2认同)

Lot*_*tus 16

您所追求的是过滤器

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

这将允许您执行以下操作:

var ary = ['three', 'seven', 'eleven'];
var aryWithoutSeven = ary.filter(function(value) { return value != 'seven' });
console.log(aryWithoutSeven); // returns ['three', 'eleven']
Run Code Online (Sandbox Code Playgroud)

在其他地方的这个帖子中也注意到了这一点:https: //stackoverflow.com/a/20827100/293492

  • 没有; 指定变量指向新对象.如果您对原始数组有其他引用,则不会受到影响. (8认同)
  • 这不会改变数组. (4认同)

Jac*_*bec 16

最简单的解决方案是:

array-用于删除某些元素的数组valueForRemove; valueForRemove-要删除的元素;

array.filter(arrayItem => !array.includes(valueForRemove));
Run Code Online (Sandbox Code Playgroud)

更简单:

array.filter(arrayItem => arrayItem !== valueForRemove);
Run Code Online (Sandbox Code Playgroud)

不漂亮,但是可以工作:

array.filter(arrayItem => array.indexOf(arrayItem) != array.indexOf(valueForRemove))
Run Code Online (Sandbox Code Playgroud)

不漂亮,但是可以工作:

while(array.indexOf(valueForRemove) !== -1) {
  array.splice(array.indexOf(valueForRemove), 1)
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然我喜欢这种方法,因为它使用不可变的数据结构,但这并不是一个包罗万象的解决方案,因为有时开发人员_确实_想要就地改变数组 (2认同)

Sha*_*are 12

看起来没有漂亮的,这是一个简单且可重复使用的ES6功能.

const removeArrayItem = (arr, itemToRemove) => {
  return arr.filter(item => item !== itemToRemove)
}
Run Code Online (Sandbox Code Playgroud)

用法:

const items = ['orange', 'purple', 'orange', 'brown', 'red', 'orange']
removeArrayItem(items, 'orange')
Run Code Online (Sandbox Code Playgroud)

  • removeArrayItem方法不会从数组中删除项目.它创建没有项目的新数组. (3认同)

Oli*_*xon 11

ES6的方式.

const commentsWithoutDeletedArray = commentsArray.filter(comment => comment.Id !== commentId);
Run Code Online (Sandbox Code Playgroud)

  • @robertotomás我更喜欢可读性而不是轻微的性能提升. (5认同)

rbe*_*uto 10

真的,我不明白为什么这不能解决

arr = arr.filter(value => value !== 'seven');
Run Code Online (Sandbox Code Playgroud)

或许你想要使用香草JS

arr = arr.filter(function(value) { return value !== 'seven' });
Run Code Online (Sandbox Code Playgroud)


gre*_*ene 9

如果您的数组中有唯一值并且排序无关紧要,则可以使用Set,并且它具有delete:

var mySet = new Set(['foo']);
mySet.delete('foo'); // Returns true.  Successfully removed.
mySet.has('foo');    // Returns false. The "foo" element is no longer present.
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 7

从数组中删除所有匹配的元素(而不是仅仅是第一个,这似乎是最常见的答案):

while ($.inArray(item, array) > -1) {
    array.splice( $.inArray(item, array), 1 );
}
Run Code Online (Sandbox Code Playgroud)

我使用jQuery来进行繁重的工作,但如果你想成为原生人,你就会明白这一点.

  • 如果找到一个项目,你运行$ .inArray两次,为什么不在第一次运行时存储索引并重新使用它?#effectiveprogramming #resourcesdonotgrowontrees.while((index = $ .inArray(item,array))> - 1)array.splice(index,1); (4认同)

Sub*_*dal 7

当您需要删除数组中多次出现的值时(例如[1,2,2,2,4,5,6])。

    function removeFrmArr(array, element) {
      return array.filter(e => e !== element);
    };
    var exampleArray = [1,2,3,4,5];
    removeFrmArr(exampleArray, 3);
    // return value like this
    //[1, 2, 4, 5]
Run Code Online (Sandbox Code Playgroud)

您可以使用splice从数组中删除单个元素,但是splice无法从数组中删除多个类似元素。

function singleArrayRemove(array, value){
  var index = array.indexOf(value);
  if (index > -1) array.splice(index, 1);
  return array;
}
var exampleArray = [1,2,3,4,5,5];
singleArrayRemove(exampleArray, 5);
// return value like this
//[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)


Eug*_*yzo 7

在所有唯一值中,您可以:

a = new Set([1,2,3,4,5]) // a = Set(5) {1, 2, 3, 4, 5}
a.delete(3) // a = Set(5) {1, 2, 4, 5} 
[...a] // [1, 2, 4, 5]
Run Code Online (Sandbox Code Playgroud)


mti*_*ani 6

在所有浏览器中运行并且没有任何框架的非常干净的解决方案是将新数组作为一个新数组并在没有要删除的项目的情况下返回它:

/**
 * @param {Array} array the original array with all items
 * @param {any} item the time you want to remove
 * @returns {Array} a new Array without the item
 */
var removeItemFromArray = function(array, item){
  /* assign a empty array */
  var tmp = [];
  /* loop over all array items */
  for(var index in array){
    if(array[index] !== item){
      /* push to temporary array if not like item */
      tmp.push(array[index]);
    }
  }
  /* return the temporary array */
  return tmp;
}
Run Code Online (Sandbox Code Playgroud)


aaa*_*aaa 5

indexOf是一个选项,但它的实现基本上是在整个数组中搜索值,因此执行时间会随着数组大小而增长。(所以我猜它在每个浏览器中都存在,我只检查了 Firefox)。

我没有要检查的 IE6,但我认为这是一个安全的赌注,您可以在几乎任何客户端机器上以这种方式每秒检查至少一百万个数组项。如果 [数组大小]*[每秒搜索次数] 可能增长到超过一百万,您应该考虑不同的实现。

基本上,您可以使用对象为数组创建索引,如下所示:

var index={'three':0, 'seven':1, 'eleven':2};
Run Code Online (Sandbox Code Playgroud)

任何健全的 JavaScript 环境都会为此类对象创建可搜索索引,以便您可以快速将键转换为值,无论对象有多少属性。

这只是基本方法,根据您的需要,您可以组合多个对象和/或数组,使相同的数据可以快速搜索到不同的属性。如果您指定您的确切需求,我可以建议更具体的数据结构。


Pen*_*Liu 5

您可以使用Lodash _.remove函数来实现这一点

var array = ['three', 'seven', 'eleven'];
var evens = _.remove(array, function(e) {
  return e !== 'seven';
});

console.log(evens);
Run Code Online (Sandbox Code Playgroud)
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
Run Code Online (Sandbox Code Playgroud)