在Javascript中从数组中删除空元素

1601

如何从JavaScript数组中删除空元素?

有没有简单直接的方法,还是必须手动循环并逐个删除?


27
如果你的问题能够明确指出“空元素”指的是什么,那将会很有帮助,因为这里的大部分答案(在我看来)错误地将其解释为“假值”元素。注意:var a = [,,]var a = [undefined, undefined]之间存在区别。前者是真正的空数组,而后者实际上有两个键,但值为undefined - Alnitak
虽然不是完全的答案,但我认为在数组中尽可能避免使用null/undefined是更好的实践。例如,如果你的null来自于使用map函数映射另一个数组时,对于某些元素返回null,那么在运行map之前尝试使用Array.filter过滤掉这些元素。这样可以使你的代码更易读/自我记录。显然,这并不适用于每种情况,但它可以应用于很多情况。 - Luke Redmore
51个回答

22

使用 Underscore/Lodash:

一般用法:

_.without(array, emptyVal, otherEmptyVal);
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);

带有空元素:

_.without(['foo', 'bar', '', 'baz', '', '', 'foobar'], '');
--> ["foo", "bar", "baz", "foobar"]

请参阅 lodash文档中的without部分


1
#compact的问题在于它会删除任何假值。因此,如果您的数组包含0值,它们也将被删除。 - Samuel Brandão

16
如果您可以使用库,我知道underscore.js有一个名为compact()的函数 http://documentcloud.github.com/underscore/ 它还有其他几个与数组和集合相关的有用函数。
这是他们文档中的一段摘要:
_.compact(array)
返回一个副本,其中删除了所有假值。在JavaScript中,false、null、0、""、未定义和NaN都是假值。
_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]

1
它还会移除已定义的非空元素,例如0。 - Timothy Gu

15

@Alnitak

实际上,如果您添加一些额外的代码,Array.filter在所有浏览器上都可以使用。请参见以下内容。

var array = ["","one",0,"",null,0,1,2,4,"two"];

function isempty(x){
if(x!=="")
    return true;
}
var res = array.filter(isempty);
document.writeln(res.toJSONString());
// gives: ["one",0,null,0,1,2,4,"two"]  

这是您需要添加到IE中的代码,但根据我的看法,过滤器和函数式编程是其价值所在。

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}

这应该是被接受的答案,因为它可以直接使用。非常感谢。 - Tony
2
@Tony 不应该,因为一个包含空字符串的元素并不等同于“空元素”,后者才是 OP 所要求的。 - Alnitak

14

鉴于其他人没有提到它,而且大多数人在其项目中都包含了下划线,您也可以使用_.without(array, *values);

_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]

13
从数组中删除未定义的元素,您可以简单地使用

array.filter(Boolean);
const array = [
  { name: "tim", age: 1 },
  undefined,
  { name: "ewrfer", age: 22 },
  { name: "3tf5gh", age: 56 },
  null,
  { name: "kygm", age: 19 },
  undefined,
];
console.log(array.filter(Boolean));


10
foo = [0, 1, 2, "", , false, 3, "four", null]

foo.filter(e => e === 0 ? true : e)

返回值

[0, 1, 2, 3, "four"]

如果您确定数组中不会有任何0,那么代码看起来会更好看一些:

foo.filter(e => e)

8

您可能会发现,通过循环数组并从中构建一个新的数组来保留所需项目比尝试循环和切割更容易,因为在循环过程中修改数组的长度可能会引入问题。

您可以像这样做:

function removeFalsyElementsFromArray(someArray) {
    var newArray = [];
    for(var index = 0; index < someArray.length; index++) {
        if(someArray[index]) {
            newArray.push(someArray[index]);
        }
    }
    return newArray;
}

实际上,这里有一个更通用的解决方案:

function removeElementsFromArray(someArray, filter) {
    var newArray = [];
    for(var index = 0; index < someArray.length; index++) {
        if(filter(someArray[index]) == false) {
            newArray.push(someArray[index]);
        }
    }
    return newArray;
}

// then provide one or more filter functions that will 
// filter out the elements based on some condition:
function isNullOrUndefined(item) {
    return (item == null || typeof(item) == "undefined");
}

// then call the function like this:
var myArray = [1,2,,3,,3,,,,,,4,,4,,5,,6,,,,];
var results = removeElementsFromArray(myArray, isNullOrUndefined);

// results == [1,2,3,3,4,4,5,6]

你可以理解为,你还可以有其他类型的筛选功能。可能比你需要的更多,但我感觉很慷慨... ;)

6
从数组中删除Falsy值的ES6语法:
var arr = [0,1,2,"test","false",false,true,null,3,4,undefined,5,"end"];

arr.filter((v) => (!!(v)==true));

//output:

//[1, 2, "test", "false", true, 3, 4, 5, "end"]

6
你应该使用过滤器来获取没有空元素的数组。以下是ES6示例:
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);

4

使用上面得到的最高投票答案中的第一个示例时,当字符串长度大于1时,我得到的是单个字符。以下是解决该问题的解决方案。

var stringObject = ["", "some string yay", "", "", "Other string yay"];
stringObject = stringObject.filter(function(n){ return n.length > 0});

如果未定义,则不返回,如果长度大于0,则返回。希望这能帮助到某些人。

返回值

["some string yay", "Other string yay"]

+1,这非常实用,与我使用字符串数组的需求完全一致。但是要注意,它会删除数字(如果它们不是以字符串形式存在),因为它们没有 .lenghth,所以 ["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123将会得到相同的结果,并且会删除数字。把这个函数替换成 String,讽刺的是,数字会被留下,但在你给出的数组中会得到相同的结果。 - aamarks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接