删除JavaScript中的数组元素-Delete与Splice

2020/09/17 13:31 · javascript ·  · 0评论

是什么使用之间的差值delete算子阵列元件上,而不是使用Array.splice方法

例如:

myArray = ['a', 'b', 'c', 'd'];

delete myArray[1];
//  or
myArray.splice (1, 1);

如果可以像删除对象一样删除数组元素,为什么还要使用splice方法呢?

delete将删除对象属性,但不会为数组重新索引或更新其长度。这使得它看起来好像是未定义的:

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

请注意,实际上并没有将其设置为value undefined,而是从数组中删除了该属性,使其显得未定义。Chrome开发人员工具通过empty在记录阵列时进行打印来明确区分此区别

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) 实际上会删除该元素,为该数组重新索引,并更改其长度。

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]

Array.remove()方法

jQuery的创建者John Resig创建了一个非常方便的Array.remove方法,我一直在项目中使用它。

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

这是一些如何使用它的示例:

// Remove the second item from the array
array.remove(1);
// Remove the second-to-last item from the array
array.remove(-2);
// Remove the second and third items from the array
array.remove(1,2);
// Remove the last and second-to-last items from the array
array.remove(-2,-1);

约翰的网站

因为delete仅从数组中的元素删除对象,所以数组的长度不会改变。拼接将删除对象并缩短数组。

以下代码将显示“ a”,“ b”,“ undefined”,“ d”

myArray = ['a', 'b', 'c', 'd']; delete myArray[2];

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

而这将显示“ a”,“ b”,“ d”

myArray = ['a', 'b', 'c', 'd']; myArray.splice(2,1);

for (var count = 0; count < myArray.length; count++) {
    alert(myArray[count]);
}

在尝试了解如何从数组中删除元素的每次出现时,我偶然发现了这个问题。这里有一个比较splice,并delete去除所有的'c'items阵列。

var items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  items.splice(items.indexOf('c'), 1);
}

console.log(items); // ["a", "b", "d", "a", "b", "d"]

items = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];

while (items.indexOf('c') !== -1) {
  delete items[items.indexOf('c')];
}

console.log(items); // ["a", "b", undefined, "d", "a", "b", undefined, "d"]

Core JavaScript 1.5参考>运算符>特殊运算符>删除运算符

删除数组元素时,数组长度不受影响。例如,如果删除a [3],则a [4]仍为a [4],而a [3]未定义。即使删除数组的最后一个元素(删除a [a.length-1]),该设置仍然成立。

splice 将与数字索引一起使用。

delete可以用于其他类型的索引。

例:

delete myArray['text1'];

值得一提的是,拼接仅适用于数组。(不能依赖对象属性遵循一致的顺序。)

要从对象中删除键值对,删除实际上是您想要的:

delete myObj.propName;     // , or:
delete myObj["propName"];  // Equivalent.

删除拼接

当您从数组中删除项目时

var arr = [1,2,3,4]; delete arr[2]; //result [1, 2, 3:, 4]
console.log(arr)

当你拼接时

var arr = [1,2,3,4]; arr.splice(1,1); //result [1, 3, 4]
console.log(arr);

如果删除删除元素,索引保持为空

而在剪接元素被删除而其余元素索引相应减少的情况下

如上所述,使用splice()似乎是一个完美的选择。Mozilla上的文档:

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

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];

myFish.splice(2, 0, 'drum'); 
// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]

myFish.splice(2, 1); 
// myFish is ["angel", "clown", "mandarin", "sturgeon"]

句法

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

参量

开始

开始更改数组的索引。如果大于数组的长度,则实际的起始索引将设置为数组的长度。如果为负,则将从头开始那么多元素。

deleteCount

一个整数,指示要删除的旧数组元素的数量。如果deleteCount为0,则不会删除任何元素。在这种情况下,您应该至少指定一个新元素。如果deleteCount大于开始时数组中剩余的元素数,则将删除数组末尾的所有元素。

如果省略deleteCount,则deleteCount将等于 (arr.length - start).

item1,item2,...

从起始索引开始,添加到数组的元素。如果不指定任何元素,splice()则只会从数组中删除元素。

返回值

包含已删除元素的数组。如果仅删除一个元素,则返回一个元素的数组。如果没有删除任何元素,则返回一个空数组。

[...]

delete的行为类似于非现实情况,它只是删除项目,但数组长度保持不变:

来自节点终端的示例:

> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]

这是一个使用slice()通过索引删除数组项的函数,它将arr作为第一个arg,将要删除的成员的索引作为第二个参数。如您所见,它实际上删除了数组的成员,并将数组长度减少了1

function(arr,arrIndex){
    return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}

上面的函数所做的是将所有成员移到索引,然后将所有成员移到索引,然后将它们连接在一起,然后返回结果。

这是一个使用上面的函数作为节点模块的示例,看到终端将很有用:

> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4 
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3

请注意,这对一个包含重复项的数组将不起作用,因为indexOf(“ c”)只会得到第一个出现,并且只会剪接并删除它找到的第一个“ c”。

如果要迭代一个大数组并有选择地删除元素,则每次删除都调用splice()会很昂贵,因为splice()每次都必须重新索引后续元素。由于数组在Javascript中是关联的,因此删除单个元素然后再重新索引数组会更有效。

您可以通过构建一个新的数组来做到这一点。例如

function reindexArray( array )
{
       var result = [];
        for( var key in array )
                result.push( array[key] );
        return result;
};

但是我认为您不能修改原始数组中的键值,这样会更有效-看起来您可能必须创建一个新数组。

请注意,您不需要检查“未定义”条目,因为它们实际上并不存在,并且for循环不会返回它们。这是阵列打印的结果,将其显示为未定义。它们似乎不存在于内存中。

如果您可以使用诸如slice()之类的更快的方法,但是它不会重新索引,那将是很好的。有人知道更好的方法吗?


实际上,您可能可以按如下所示进行处理,这可能会更高效,更明智地执行以下操作:

reindexArray : function( array )
{
    var index = 0;                          // The index where the element should be
    for( var key in array )                 // Iterate the array
    {
        if( parseInt( key ) !== index )     // If the element is out of sequence
        {
            array[index] = array[key];      // Move it to the correct, earlier position in the array
            ++index;                        // Update the index
        }
    }

    array.splice( index );  // Remove any remaining elements (These will be duplicates of earlier items)
},

你可以用这样的东西

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]

为什么不只是过滤?我认为这是在js中考虑数组的最清晰方法。

myArray = myArray.filter(function(item){
    return item.anProperty != whoShouldBeDeleted
});

可以通过在应用delete运算符和splice()方法后记录每个数组的长度来看出差异例如:

删除运算符

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];

console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees.length); // 5

所述delete操作员删除该数组的元素,但该元素的“占位符”仍然存在。oak已被删除,但仍需要占用阵列中的空间。因此,数组的长度保持为5。

splice()方法

var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);

console.log(trees); // ["redwood", "bay", "cedar", "maple"]
console.log(trees.length); // 4

splice()方法会完全删除目标值 “占位符”。oak已被删除,以及它在阵列中占用的空间。数组的长度现在为4。

其他人已经比较正常delete使用splice

与另一个有趣的比较是deleteundefined刚设置的数组项相比,删除的数组项使用更少的内存undefined;

例如,此代码不会完成:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

它产生此错误:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

因此,您可以看到undefined实际上占用了堆内存。

但是,如果您还是deleteary项目(而不是仅将其设置为undefined),代码也会慢慢完成:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

这些是极端的例子,但它们delete说明了我从未见过有人提及的地方。

function remove_array_value(array, value) {
    var index = array.indexOf(value);
    if (index >= 0) {
        array.splice(index, 1);
        reindex_array(array);
    }
}
function reindex_array(array) {
   var result = [];
    for (var key in array) {
        result.push(array[key]);
    }
    return result;
}

例:

var example_arr = ['apple', 'banana', 'lemon'];   // length = 3
remove_array_value(example_arr, 'banana');

香蕉被删除,数组长度= 2

它们是具有不同目的的不同事物。

splice是特定于阵列的,用于删除时,将从阵列中删除条目并将所有先前的条目向上移动以填补空白。(它也可以用于插入条目,或同时插入两个条目。)splice将更改length数组的大小(假设它不是no-op调用:)theArray.splice(x, 0)

delete不是特定于数组的;它设计用于对象:它从使用对象的对象中删除属性(键/值对)。它仅适用于数组,因为JavaScript 中的标准(例如,非类型化)数组根本不是真正的数组 *,它们是对某些属性进行特殊处理的对象,例如名称为“数组索引”的对象(定义为字符串名称“ ...其数值i在范围内+0 ≤ i < 2^32-1”)和length当您delete用来删除一个数组条目时,它所做的就是删除条目。它不会移动其他条目来填补空白,因此数组变为“稀疏”(某些条目完全丢失)。它对没有影响length

该问题的两个当前答案错误地指出使用delete“将条目设置为undefined”。那是不对的。完全删除条目(属性),从而留下空白。

让我们用一些代码来说明不同之处:

console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a.splice(0, 1);
console.log(a.length);            // 4
console.log(a[0]);                // "b"

console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
delete a[0];
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // false
console.log(a.hasOwnProperty(0)); // false

console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length);            // 5
a[0] = undefined;
console.log(a.length);            // still 5
console.log(a[0]);                // undefined
console.log("0" in a);            // true
console.log(a.hasOwnProperty(0)); // true

* (这是我贫乏的小博客上的帖子)

目前有两种方法可以做到这一点

  1. 使用splice()

    arrayObject.splice(index, 1);

  2. 使用删除

    delete arrayObject[index];

但是我总是建议对数组对象使用拼接,对对象属性使用删除,因为删除不会更新数组长度。

好吧,假设我们下面有这个数组:

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

让我们先删除:

delete arr[1];

结果如下:

[1, empty, 3, 4, 5];

空!让我们得到它:

arr[1]; //undefined

因此意味着仅删除了该值,并且现在未定义该值,因此长度是相同的,并且它将返回true

让我们重置数组,这次用拼接完成它:

arr.splice(1, 1);

这是这次的结果:

[1, 3, 4, 5];

如您所见,数组长度已更改,现在arr[1]3 ...

同样,这将返回数组中已删除的项目,[3]在这种情况下...

如果阵列较小,可以使用filter

myArray = ['a', 'b', 'c', 'd'];
myArray = myArray.filter(x => x !== 'b');

性能

关于功能差异,已经有了许多不错的答案-因此,在此我要重点介绍性能。今天(2020.06.25)我针对Chrome 83.0,Safari 13.1和Firefox 77.0执行测试,以解决有问题的解决方案以及从所选答案中获得的解决方案

结论

  • splice(B)的解决方案是快速的小型和大阵列
  • delete(A)的解决方案是为最快大中型快速对于小阵列
  • filter(E)的解决方案是最快的Chrome和Firefox的小数组(但最慢的Safari浏览器,并为缓大阵列)
  • 解决方案D相当慢
  • 解决方案C不适用于Chrome和Safari中的大型阵列

在此处输入图片说明

细节

我对解决方案A
B
C
D
E
执行以下测试
(我)

  • 对于小数组(4个元素)-您可以在此处运行测试
  • 对于大数组(1M个元素)-您可以在此处运行测试

Chrome的结果范例

在此处输入图片说明

最简单的方法可能是

var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1]; // ['a', undefined, 'c', 'd']. Then use lodash compact method to remove false, null, 0, "", undefined and NaN
myArray = _.compact(myArray); ['a', 'c', 'd'];

希望这可以帮助。参考:https : //lodash.com/docs#compact

对于那些想要使用Lodash的人可以使用:
myArray = _.without(myArray, itemToRemove)

或者像我在Angular2中使用的

import { without } from 'lodash';
...
myArray = without(myArray, itemToRemove);
...

delete:delete将删除对象属性,但不会为数组重新索引或更新其长度。这使得它看起来好像是未定义的:

splice:实际上删除元素,为数组重新索引,并更改其长度。

从最后删除元素

arrName.pop();

首先删除元素

arrName.shift();

从中间删除

arrName.splice(starting index,number of element you wnt to delete);

Ex: arrName.splice(1,1);

从最后删除一个元素

arrName.splice(-1);

使用数组索引号删除

 delete arrName[1];

如果要删除的元素位于中间(例如,我们要删除索引为1的“ c”),则可以使用:

var arr = ['a','b','c'];
var indexToDelete = 1;
var newArray = arr.slice(0,indexToDelete).combine(arr.slice(indexToDelete+1, arr.length))

IndexOf还接受引用类型。假设以下情况:

var arr = [{item: 1}, {item: 2}, {item: 3}];
var found = find(2, 3); //pseudo code: will return [{item: 2}, {item:3}]
var l = found.length;

while(l--) {
   var index = arr.indexOf(found[l])
      arr.splice(index, 1);
   }
   
console.log(arr.length); //1

不同的是:

var item2 = findUnique(2); //will return {item: 2}
var l = arr.length;
var found = false;
  while(!found && l--) {
  found = arr[l] === item2;
}

console.log(l, arr[l]);// l is index, arr[l] is the item you look for
function deleteFromArray(array, indexToDelete){
  var remain = new Array();
  for(var i in array){
    if(array[i] == indexToDelete){
      continue;
    }
    remain.push(array[i]);
  }
  return remain;
}

myArray = ['a', 'b', 'c', 'd'];
deleteFromArray(myArray , 0);

//结果:myArray = ['b','c','d'];

本文地址:http://javascript.askforanswer.com/shanchujavascriptzhongdeshuzuyuansu-deleteyusplice.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!