Javascript:如何从数组中清除未定义的值

Javascript: How to clear undefined values from an array

提问人:KT. 提问时间:3/7/2012 更新时间:2/2/2023 访问量:28440

问:

我正在尝试遍历一个数组并删除和跳过元素,直到只有一个元素存在。我尝试过拼接,但它搞砸了我的循环,因为 arr[1] 中的元素然后变成了 arr[0] 等。

假设有 10 个人。我想删除人员 1,然后保留人员 2,然后删除人员 3 并保留人员 4。这种模式将一直持续到只剩下一个。

任何形式的帮助都可以。

JavaScript 数组 undefined-index

评论

0赞 nnnnnn 3/7/2012
“直到只剩下一个”是什么意思?在通过数组一次后,您将将其从 10 个元素(人)削减到 5 个元素(人)——你是说你想继续重复该过程(重复遍历),直到数组中只有一个元素?
0赞 trumank 3/7/2012
如果你只想要一个元素...那为什么需要循环呢?
0赞 Cameron 3/7/2012
@MathWizz,这也是我的想法,可以在不需要循环的情况下计算剩余元素的位置。
0赞 KT. 3/8/2012
是的,我将重复这个过程,直到只剩下一个。

答:

9赞 Ruan Mendes 3/7/2012 #1

拼接时,只需递减循环索引即可。

有很多很好的建议,我将发布不同选项的代码,您可以决定使用哪个

拼接 http://jsfiddle.net/mendesjuan/aFvVh/ 时的递减指数

var undef;
var arr = [1,2, undef, 3, 4, undef];
for (var i=0; i < arr.length; i++) {
    if ( arr[i] === undef ) {
        arr.splice(i,1);
        i--;
    }
}

向后循环 http://jsfiddle.net/mendesjuan/aFvVh/1/

var undef;
var arr = [1,2, undef, 3, 4, undef];
for (var i=arr.length - 1; i >=0; i--) {
    if ( arr[i] === undef ) {
        arr.splice(i,1);
    }
}

复制到新的阵列 http://jsfiddle.net/mendesjuan/aFvVh/2/

var undef;
var arr = [1,2, undef, 3, 4, undef];
var temp = [];
for (var i=0; i < arr.length; i++) {
    if ( arr[i] !== undef ) {
        temp.push(arr[i])
    }
}
arr = temp;

使用过滤器,这只是创建新数组的一种奇特方式

var undef;
var arr = [1,2, undef, 3, 4, undef];
arr = arr.filter(function(item){
    return item !== undef;
});

在所有这些示例的末尾,arr 将是 [1,2,3,4]

性能

IE 11、FF 和 Chrome 都认为这是最快的。10 倍 (Chrome),20 倍 (IE 11) 与 将项目放入新数组相比,速度也很慢。查看 http://jsperf.com/clean-undefined-values-from-array2Array.spliceArray.filter.Array.slice

看到 IE 在这里处于领先地位,并看到 Chrome 落后于 FF 和 IE,我真的很惊讶。我想我从来没有用这个结果进行过测试。

9赞 Simon Wang 3/7/2012 #2

在迭代过程中,您不应该更改集合,不仅是 JavaScript,而是所有语言,定义一个新数组并在其中添加要删除的数组,然后迭代该数组以从第一个数组中删除。

评论

0赞 Ruan Mendes 3/7/2012
如果您控制索引,则可以更改它。但是,这比我的建议更不容易出错
3赞 nnnnnn 3/7/2012
将要保留的数组添加到第二个数组中,然后在最后用第二个数组替换第一个数组怎么样?省去了第二次迭代的麻烦。
0赞 Simon Wang 3/7/2012
我的意见是,我们应该尽量保持我们的代码简单易读,我的权宜之计只是告诉我,编写一个奇怪的复杂循环只会带来错误并混淆其他人
0赞 Ruan Mendes 3/8/2012
我误读了 Simon 的建议,真正简单的方法是 nnnnnn 建议的(在此答案下),将其复制到新数组中
0赞 KT. 3/8/2012
我最终使用了 3 个数组,第一个作为原始数组,这是循环的基础。在循环中使用 2 个数组。第二个数组包含在该迭代中跳过的数组,另一个数组是空数组。在每次迭代结束时,我都会这样做。 我不确定这是否是最好的解决方案,但它是有道理的,就像西蒙所说的让它更简单并且它奏效了。arr1 = arr2;arr2 = arr3;
-1赞 avgusti 3/7/2012 #3
  while(yourarray.length>1) //only one left
    {
    // your code
    }

评论

2赞 Cheery 3/7/2012
length是数组的属性,而不是函数。
3赞 nnnnnn 3/7/2012 #4

向后循环。(因此,删除项目不会影响尚未处理的元素的索引。

0赞 bPratik 3/7/2012 #5

没有确切地收集您想要实现的目标,但我觉得您依赖于数组中某个项的位置索引来继续您的程序。在这种情况下,我建议使用散列数组,即键<>值对数组。

在这种情况下,请始终指向您最初放置在其中的项目。因此,您可以在逻辑/数字上循环,而不必担心位置的变化。arr["2"]

谨防类型转换风险和陷阱!

0赞 DdD 3/7/2012 #6

最好的办法是创建数组的副本,然后从原始数组进行拼接。

或者只是使用集合(key->value)并删除键,例如

 People = {a: "Person A", b: "Person B", c:"Person C"};
 delete People.a;
 delete People.c;  //now the People collection only has 1 entry.

你可以用数字替换 a,b,c 作为例子,

 People = {0: "Person A", 1: "Person B", 2:"Person C"};
 delete People[0];
 delete People[1];

评论

0赞 Ruan Mendes 3/7/2012
你错过了重点,OP知道要拼接,问题是删除项目后索引过时了
0赞 DdD 3/7/2012
@Juan Mendes,最好使用键>值集合
0赞 trumank 3/7/2012 #7
function removeUndefined(array)
{
    var i = 0;
    while (i < array.length)
        if (typeof array[i] === 'undefined')
            array.splice(i, i);
        else
            i++;
    return array;
}

编辑:我是根据标题写的。看起来这个问题问的是完全不同的东西。

评论

2赞 shenhengbin 3/7/2012
如果 array[i] 为空或 false,或为 0,则它也将被删除。
0赞 nnnnnn 3/7/2012
我想你的意思是.splice(i, 1)
0赞 trumank 6/13/2012
@shenhengbin我已经解决了这个问题。
0赞 shenhengbin 3/7/2012 #8

这是一个示例

<script lanauge = "javascript">
    var arr = ["1","2","3","4"];
    delete arr[1];// arr[1] is undefined
    delete arr[2];// arr[2] is undefined

    // now arr.length is 4

    var todelete = [];
    for (i = 0 ; i < arr.length ;i++)
    {
        if (typeof arr[i] == 'undefined') todelete.push(i);
    }

    todelete.sort(function(a, b) { return b-a }); // make the indeies from big to small

    for (i = 0;i < todelete.length; i ++)
    {
        arr.splice(todelete[i],1);
    }

    // now arr.length is 2

</script>

评论

0赞 nnnnnn 3/7/2012
这种方法并没有按照评论所说的那样做。如果没有回调函数,它将执行升序字典排序。.sort()
0赞 Cameron 3/7/2012 #9

这可能不是你想要的,但你可以很容易地计算出这个过程结束时的最后一个元素是什么,然后抓住它。假设数组的元素是连续的,并且从 arr[0] 开始,您可以找到:

var logBase2OfLength = Math.floor(Math.log(arr.length) / Math.log(2));
var finalElement = arr[(1 << logBase2OfLength) - 1];

基本上,如果取 2 的整数幂小于或等于数组中的元素数,则该元素在所有循环和删除后将保留的位置。

1赞 2 revsajax333221 #10

令人惊讶的是,没有人回答最好和正确的方式:

  1. 创建新阵列
  2. 遍历旧数组,并且只将要保留的元素推送到新数组

一些功劳归功于@nnnnnn评论

评论

0赞 Ruan Mendes 4/6/2015
与使用拼接 jsperf.com/clean-undefined-values-from-array2/2 相比,它相当慢
3赞 equivalent8 12/13/2012 #11

如果您正在使用 CoffeeScript,那么要从 Array 中删除 undefined,请执行此操作

values = ['one', undefined]
values = (item for item in values when item != undefined) 

values
/* => ['one'] */
29赞 alexoviedo999 12/15/2014 #12

过滤虚假项目:

var a=[1,2,"b",0,{},"",NaN,3,undefined,null,5];
var b=a.filter(Boolean); // [1,2,"b",{},3,5]

评论

0赞 Tatarin 7/22/2016
@alexoviedo999 迄今为止我见过的最好的一个。我通常会检查undefineds或true
0赞 John Rand 1/1/2018
alexoviedo999 哇!谢谢!
0赞 Vishal Kumar 3/18/2018 #13
>If you are getting undefined during deletion of the key-pair, Then to prevent "undefined" you can try code given below to delete key-pair  


   1) test = ["1","2","3","4",""," "];
   2) var delete = JSON.stringify(test);   
      case1) delete = delete.replace(/\,""/g,'');  
         or  
      case2) delete = delete.replace(/\," "/g,'');  
         or  
      case3) delete = delete.replace(/\,null/g,'');  

   3) var result = JSON.parse(delete);  
0赞 Judith lobo 2/2/2023 #14

只是 [NaN, 未定义, null, 0, 1, 2, 2000, Infinity].filter(布尔值)