从js数组中删除值而无需重新排序键

时间:2013-03-05 21:50:26

标签: javascript

我有一个数组,我只想删除一个元素,但没有重新排序键。有没有使用删除或重建整个数组的简单方法?

或者在删除后清理以清除未定义的值,再次修复长度。

var array = ["valueone", "valuetwo"];

console.dir(array); // keys 0 and 1
array.splice(0, 1);
console.dir(array); // key 1 is now 0, do not want!

3 个答案:

答案 0 :(得分:6)

您可以delete数组的元素:

a = ['one', 'two'];
delete a[0];

// a is now [undefined, 'two'];

或者,将a[0]明确设置为undefined

请注意,系统会自动维护数组.length参数。如果您故意将其设置为更高的数字,那么您只需为缺少的密钥获得一整套undefined值:

a.length = 10;
// a is now [undefined, 'two', undefined x 8]

如果您不接受这些语义,则应考虑使用Object。这将保留您的密钥,并且可能更有效,但您将失去.length属性。

答案 1 :(得分:1)

你不能只是将值显式设置为undefined或null或空字符串。你想要实现什么目标?

var arr = ['aaaa','bbb','ccc','ddd'];
    arr[0]= undefined;
    //or
    arr[0]= null;
    ///or
    arr[0]= "";
    arr.length; <--- 4

答案 2 :(得分:1)

更新2018-09-07

在我看来,这个答案并不是很好。我提供了一个关于 How do I remove a property from a JavaScript Object 的答案,这些答案多年来得到了我的更多关注,并涵盖了这个案例并进行了更详细的介绍。

关键是,您应该使用Array.prototype.spliceArray.prototype.slice

array.splice(start, n)返回带有array个连续元素的索引start的{​​{1}}子集,并从原始数组中删除此子集,在此过程中创建一个新数组。

n

let array = [1,2,3,4,5,6]; array.splice(2,3); // [3,4,5] array; // [1,2,6] 会将array.slice(start, end)的一个子集从索引array返回到索引start,而不会改变原始内容。该行为与end略有不同,这就是我更喜欢将其称为splice的原因。

array.slice(start, start + n)

当然,可以将索引设置为像let array = [1,2,3,4,5,6]; array.slice(2, 2 + 3); // [3,4,5] array; // [1,2,3,4,5,6] null这样的标记值,但是如果您希望删除后数组保持相同的顺序,也许你应该改变你的方法 - 为什么""必须在索引1?如果内容始终与访问它们所需的密钥相同,那么即使在此数据结构中保存了哪些有用的信息?


原始答案如下。如果我要保留原文,也许我应该详细说明为什么这是一个糟糕的建议。

  

您可以使用javascript的"valuetwo"关键字。

delete

不要这样做。如果你的数组是同类的(因为它应该是),那么这将通过引入第二种类型(delete array[index]; )来破坏你的数组。您应该使用上面讨论的undefined,这将创建一个省略指定范围的新数组。

  

不幸的是,这会在数组

中创建一个array.splice()索引
undefined

个案。

  

你也可以这样做:

var arr = ['pie', 'cake', 'fish'];
delete arr[1];
arr; // ['pie', undefined, 'fish']

你可以,但你不应该。这不仅是不必要的,而且没有做任何有用的事情(因为它所做的只是调用var arr = [9,8,7,6]; arr[1] = null; arr; // [9,null,7,6] arr.length; // 4 var i = -1; while(++i < arr.length){ if(arr[i] && typeof(arr[i] === "number")){ alert(arr[i]); } } ),但它实际上已经破坏了。

alert

您可能希望这只是打印我们的元素,如果它是一个非零数字,但实际上也会运行if(arr[i] && typeof(arr[i] === "number")){ alert(arr[i]); } "foo"[]之类的值,因为{ {1}}将始终返回值document.createElement("p"),这是一个非空字符串,这是真实的,因此将评估为真。这意味着typeof(arr[i] === "number")被调用的唯一要求是"boolean"是真实的。整个语言中只有六个值会导致if语句不执行,而且这些值是:

  • alert
  • arr[i]
  • undefined
  • null(发音为“empty string”)
  • 0
  • ""
  

或者,如果您不需要使用数组,则可以使用对象并使一切变得更容易:

false

这会立即消除使用数组的所有优点。现在你有一个数据集,它可能是异构的,也可能不是异构的,不能以任何合理的方式过滤,映射,减少或转换,你必须诉诸NaN之类的东西(这是非常错误的 - 如果你敢于使用像jQuery这样的库来进行迭代,那就很容易了。幸运的是,今天我们有像var obj = { 0: "first", 1: "second", 2: "third" }; delete obj[1]; obj; // {0: "first", 2: "third"} for(var i in obj){ alert(obj[i]); } 这样的花哨的东西,但这并不是造成糟糕数据结构的借口。

  

获取对象的长度:

for(i in obj)

同样,对于数组,这是不必要的。

  

但请记住,对象按Object.keys(obj).map(k => obj[k]).forEach(function(el){ ... })对其索引进行排序,而不是&gt;按名字。但这不应该导致路障。

     

按字母顺序对对象的索引进行排序:

getLength = function(obj){
    var i = 0, l = 0;
    for(i in obj){
        l++;
    }
    return l;
}
getLength(obj); // 3
date of creation

无论如何,对象的重点在于它的属性是未排序的。对未排序的列表进行排序几乎没有任何用处。

只是为了说明在做数组时有多好的数组:

sortObject = function (){
    var arr = [], i;
    for(i in this){
        arr.push({index:i,content:this[i]});
        delete this[i];
    }
    arr.sort();
    for(i in arr){
        var item = arr[i];
        this[item.index] = item.content;
    }
    return this; // make chainable
}
var obj = {
    acronym: "OOP",
    definition: "Object-Oriented Programming",
    article: "http://wikipedia.org/OOP"
};
sortObject.apply(obj); // indices are "acronym", "article", "definition"

如果array.sort(fn) let array = ["pie", "cake", "fish", "brownie", "beef", ...]; /* do some stuff... */ array .filter(el => exclude.indexOf(el) === -1) .forEach(function(el){ console.log(el); }); ,则会将以下内容记录到控制台:

exclude

试着想象使用此答案的前一版本中的方法可以使用多少不必要的代码行。

  
     

希望这有帮助

希望此更新有所帮助。