如何从 JavaScript 中的数组中删除空元素?
有没有一种简单的方法,还是我需要遍历它并手动删除它们?
var a = [,,]
和 var a = [undefined, undefined]
获得的结果有所不同。前者确实是空的,但后者实际上有两个键,但具有 undefined
值。
null
/undefined
。例如,如果您的 null
来自对另一个数组的映射,其中 map 函数为某些元素返回 null
,请尝试在运行映射之前 Array.filter
排除这些元素。使您的代码更具可读性/自记录性。显然,这并不适用于每个用例,但它可以应用到很多地方。
几个简单的方法:
var arr = [1,2,,3,,-3,null,,0,,undefined,4,,4,,5,,6,,,,];
arr.filter(n => n)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Number)
// [1, 2, 3, -3, 4, 4, 5, 6]
arr.filter(Boolean)
// [1, 2, 3, -3, 4, 4, 5, 6]
或 - (仅适用于“文本”类型的单个数组项)
['','1','2',3,,'4',,undefined,,,'5'].join('').split('');
// output: ["1","2","3","4","5"]
或 - 经典方式:简单迭代
var arr = [1,2,null, undefined,3,,3,,,0,,,[],,{},,5,,6,,,,],
len = arr.length, i;
for(i = 0; i < len; i++ )
arr[i] && arr.push(arr[i]); // copy non-empty values to the end of the array
arr.splice(0 , len); // cut the array and leave only the non-empty values
// [1,2,3,3,[],Object{},5,6]
jQuery:
var arr = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
arr = $.grep(arr, n => n == 0 || n);
// [1, 2, 3, 3, 0, 4, 4, 5, 6]
编辑:这个问题几乎在九年前就得到了回答,当时 Array.prototype
中没有很多有用的内置方法。
现在,当然,我建议您使用 filter
方法。
请记住,此方法将返回一个新数组,其中包含通过您提供给它的回调函数标准的元素。
例如,如果您要删除 null
或 undefined
值:
var array = [0, 1, null, 2, "", 3, undefined, 3,,,,,, 4,, 4,, 5,, 6,,,,]; var filters = array.filter(function (el) { return el != null; });控制台.log(过滤);
这将取决于您认为什么是“空的”,例如,如果您正在处理字符串,上述函数不会删除空字符串的元素。
我经常看到的一种典型模式是删除 falsy 元素,其中包括空字符串 ""
、0
、NaN
、null
、undefined
和 { 6}。
您可以传递给 filter
方法、Boolean
构造函数,或在过滤条件函数中返回相同的元素,例如:
var filtered = array.filter(Boolean);
或者
var filtered = array.filter(function(el) { return el; });
这两种方式都有效,因为第一种情况下的 filter
方法将 Boolean
构造函数作为函数调用,转换值,而在第二种情况下,filter
方法在内部转换回调的返回值隐含到 Boolean
。
如果您正在使用稀疏数组,并且您正试图摆脱“漏洞”,您可以使用 filter
方法传递一个返回 true 的回调,例如:
var sparseArray = [0, , , 1, , , , , 2, , , , 3], cleanArray = sparseArray.filter(function () { return true });控制台.log(cleanArray); // [ 0, 1, 2, 3 ]
旧答案:不要这样做!
我使用这种方法,扩展原生 Array 原型:
Array.prototype.clean = function(deleteValue) {
for (var i = 0; i < this.length; i++) {
if (this[i] == deleteValue) {
this.splice(i, 1);
i--;
}
}
return this;
};
test = new Array("", "One", "Two", "", "Three", "", "Four").clean("");
test2 = [1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,];
test2.clean(undefined);
或者您可以简单地将现有元素推送到其他数组中:
// Will remove all falsy values: undefined, null, 0, false, NaN and "" (empty string)
function cleanArray(actual) {
var newArray = new Array();
for (var i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i]);
}
}
return newArray;
}
cleanArray([1, 2,, 3,, 3,,,,,, 4,, 4,, 5,, 6,,,,]);
splice
调用真的成本很高,因为它们必须重新编号所有数组键以缩小差距。
Object.defineProperty
扩展 Array.prototype
以使新函数成为 不可枚举的属性,然后避免由将 .hasOwnProperty
放在每个循环中。
如果您需要删除所有空值(“”、null、未定义和 0):
arr = arr.filter(function(e){return e});
要删除空值和换行符:
arr = arr.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")});
例子:
arr = ["hello",0,"",null,undefined,1,100," "]
arr.filter(function(e){return e});
返回:
["hello", 1, 100, " "]
更新(基于 Alnitak 的评论)
在某些情况下,您可能希望在数组中保留“0”并删除其他任何内容(null、未定义和“”),这是一种方法:
arr.filter(function(e){ return e === 0 || e });
返回:
["hello", 0, 1, 100, " "]
function(e){return !!e}
!!e
将包括 NaN(与 0 不同),而 e
不会(如 0)。
var myarr=[1, 2,, 3,, 3,undefined,,"",,0, 4,, 4,, 5,, 6,,,,].filter(Boolean);
删除 undefined,"" 和 0
只需一个班轮:
[1, false, "", undefined, 2].filter(Boolean); // [1, 2]
或使用 underscorejs.org:
_.filter([1, false, "", undefined, 2], Boolean); // [1, 2]
// or even:
_.compact([1, false, "", undefined, 2]); // [1, 2]
Boolean
作为一个函数工作......
Boolean
视为一个函数,它只会返回 true
或 false
,无论该值是真的/假的。
(true).constructor === Boolean
。然后告诉我我们是否可以使用 JS 中的其他内置插件来做到这一点。 ;)) (当然不包括其他 5 个内置构造函数。(字符串、数组、对象、函数、数字))
如果您有 Javascript 1.6 或更高版本,则可以使用 Array.filter
使用一个简单的 return true
回调函数,例如:
arr = arr.filter(function() { return true; });
因为 .filter
会自动跳过原始数组中缺失的元素。
上面链接的 MDN 页面还包含一个很好的 filter
错误检查版本,可用于不支持正式版本的 JavaScript 解释器。
请注意,这不会删除 null
条目或具有显式 undefined
值的条目,但 OP 明确要求“丢失”条目。
undefined
作为其给定值。
为了去除孔,你应该使用
arr.filter(() => true)
arr.flat(0) // New in ES2019
用于删除空洞、空和未定义:
arr.filter(x => x != null)
用于删除空洞,并且,假 (null, undefined, 0, -0, 0n, NaN, "", false, document.all) 值:
arr.filter(x => x)
arr = [, null, (void 0), 0, -0, 0n, NaN, false, '', 42]; console.log(arr.filter(() => true)); // [null, (void 0), 0, -0, 0n, NaN, false, '', 42] console.log(arr.filter(x => x != null)); // [0, -0, 0n, NaN, false, "", 42] console.log(arr.filter(x => x)); // [42]
笔记:
孔是一些没有元素的数组索引。
arr = [, ,];
console.log(arr[0], 0 in arr, arr.length); // undefined, false, 2; arr[0] is a hole
arr[42] = 42;
console.log(arr[10], 10 in arr, arr.length); // undefined, false, 43; arr[10] is a hole
arr1 = [1, 2, 3];
arr1[0] = (void 0);
console.log(arr1[0], 0 in arr1); // undefined, true; a[0] is undefined, not a hole
arr2 = [1, 2, 3];
delete arr2[0]; // NEVER do this please
console.log(arr2[0], 0 in arr2, arr2.length); // undefined, false; a[0] is a hole
以上所有方法都返回给定数组的副本,而不是就地修改它。
arr = [1, 3, null, 4];
filtered = arr.filter(x => x != null);
console.log(filtered); // [1, 3, 4]
console.log(arr); // [1, 3, null, 4]; not modified
[, ,]
arr.filter(x => x)
,JS 将检查 x 是真还是假,即 if (x)
,因此只有真值将分配给新列表。
干净的方式来做到这一点。
var arr = [0,1,2,"Thomas","false",false,true,null,3,4,undefined,5,"end"];
arr = arr.filter(Boolean);
// [1, 2, "Thomas", "false", true, 3, 4, 5, "end"]
undefined
;这基本上删除了所有虚假值。
实际上,您可以使用 ES6+
方法,假设数组如下:
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9];
答案可能是以下两种方式之一:
第一种方式: const clearArray = arr.filter(i => i); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
第二种方式: const clearArray = arr.filter(Boolean); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
const arr = [1,2,3,undefined,4,5,6,undefined,7,8,undefined,undefined,0,9]; console.log("arr.filter(i => i)", arr.filter(i => i)); console.log("arr.filter(Boolean)", arr.filter(Boolean));
ES6:
let newArr = arr.filter(e => e);
简单的 ES6
['a','b','',,,'w','b'].filter(v => v);
[1, 'two', null, undefined, , NaN, false, true, 0].filter(v => v)
。
使用下划线/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 documentation for without。
如果使用库是一种选择,我知道 underscore.js 有一个名为 compact() http://documentcloud.github.com/underscore/ 的函数,它还有其他几个与数组和集合相关的有用函数。
以下是他们文档的摘录:
_.compact(array) 返回删除所有虚假值的数组副本。在 JavaScript 中,false、null、0、""、undefined 和 NaN 都是假的。 _.compact([0, 1, false, 2, '', 3]); => [1, 2, 3]
@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 添加的代码,但过滤器和函数式编程值得 imo。
//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;
};
}
由于没有其他人提及它并且大多数人在他们的项目中包含下划线,因此您也可以使用 _.without(array, *values);
。
_.without(["text", "string", null, null, null, "text"], null)
// => ["text", "string", "text"]
要从数组中删除未定义的元素,您可以简单地使用
const array = [ { name: "tim", age: 1 }, undefined, { name: "ewrfer", age: 22 }, { name: "3tf5gh", age: 56 }, null, { name: "kygm" , 年龄: 19 }, 未定义, ]; console.log(array.filter(Boolean));
您可能会发现循环遍历数组并从要保留在数组中的项目中构建一个新数组比尝试按照建议进行循环和拼接更容易,因为在循环时修改数组的长度过度会带来问题。
你可以这样做:
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]
你明白了 - 然后你可以有其他类型的过滤器功能。可能比你需要的多,但我感觉很慷慨......;)
this(ES6) 怎么样:从数组中删除 Falsy 值。
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"]
您应该使用过滤器来获取没有空元素的数组。 ES6 示例
const array = [1, 32, 2, undefined, 3];
const newArray = array.filter(arr => arr);
当使用上面投票最高的答案时,第一个例子,我得到了字符串长度大于 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"]
["", "some string yay", "", "", 123, "Other string yay"].filter(function(n){ return n.length > 0}) //gives your same result removing 123
替换该函数......具有讽刺意味的是,使用字符串会留下数字,但会在给定数组中给出相同的结果。
我只是将我的声音添加到上面的“使用全局构造函数调用 ES5 的 Array..filter()
”golf-hack,但我建议使用 Object
而不是上面建议的 String
、Boolean
或 Number
。
具体来说,ES5 的 filter()
已经不会为数组中的 undefined
元素触发;因此,一个普遍返回 true
的函数(它返回 所有 个元素 filter()
命中)必然只返回非 undefined
元素:
> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(function(){return true})
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]
但是,写出 ...(function(){return true;})
比写出 ...(Object)
长;在任何情况下,Object
构造函数的返回值都是某种对象。与上面建议的原始装箱构造函数不同,没有可能的对象值是错误的,因此在布尔设置中,Object
是 function(){return true}
的简写。
> [1,,5,6,772,5,24,5,'abc',function(){},1,5,,3].filter(Object)
[1, 5, 6, 772, 5, 24, 5, 'abc', function (){}, 1, 5, 3]
someArray.filter(String);
实际上等同于 someArray.filter(function(x){ return String(x); });
。如果要删除所有虚假值 someArray.filter(Boolean);
可以删除 0、-0、NaN、false、''、null 和 undefined。
Object
构造函数而不是 return true
方法的性能开销。 @robocat OP 要求删除空元素,而不是空元素。
var data = [null, 1,2,3];
var r = data.filter(function(i){ return i != null; })
console.log(r)
[1,2,3]
删除所有空元素
如果一个数组包含空对象、数组和字符串以及其他空元素,我们可以使用以下方法删除它们:
const arr = [ [], ['not', 'empty'], {}, { key: 'value' }, 0, 1, null, 2, "", "here", " ", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ] let filters = JSON.stringify( arr.filter((obj) => { return ![null, undefined, ''].includes (obj) }).filter((el) => { return typeof el != "object" || Object.keys(el).length > 0 }) ) console.log(JSON.parse(filtered))
简单压缩(从数组中删除空元素)
使用 ES6:
const arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,] 让过滤 = arr.filter((obj ) => { return ![null, undefined].includes(obj) }) console.log(filtered)
使用纯 Javascript ->
var arr = [0, 1, null, 2, "", 3, undefined, 3, , , , , , 4, , 4, , 5, , 6, , , ,] var filters = arr.filter(function ( obj) { return ![null, undefined].includes(obj) }) console.log(filtered)
您可以将过滤器与索引和 in
运算符一起使用
让 a = [1,,2,,,3];让 b = a.filter((x,i)=> i in a);控制台.log({a,b});
let a=[]; a.abc=1
- 但通常没有人这样做(这样做非常奇特 - 因为您可以只使用数组,例如对象 {}
)。而且,当您以如此奇特的方式使用数组时,标准 JS 数组方法(如 map
、filter
等)将忽略此类键值对 - 我的解决方案基于 filter
并忽略它。很明显,OP 询问标准 JS 数组(因为他没有提到这种奇特的用例)
in
运算符返回了数组中的值。所以我认为只有当数组中的值与想要过滤的索引号相同时它才会起作用。但我现在看到 in
指的是数组的属性(如索引),而不是值。
那个怎么样:
js> [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,].filter(String).join(',')
1,2,3,3,0,4,4,5,6
另一种方法是利用数组的长度属性:将非空项打包在数组的“左侧”,然后减小长度。它是一种就地算法——不分配内存,对垃圾收集器来说太糟糕了——并且它具有非常好的最佳/平均/最坏情况行为。
与此处的其他解决方案相比,此解决方案在 Chrome 上的速度要快 2 到 50 倍,在 Firefox 上要快 5 到 50 倍,您可能会在此处看到:http://jsperf.com/remove-null-items-from-array
下面的代码将不可枚举的 'removeNull' 方法添加到 Array 中,该方法返回 'this' 用于菊花链:
var removeNull = function() {
var nullCount = 0 ;
var length = this.length ;
for (var i=0, len=this.length; i<len; i++) { if (!this[i]) {nullCount++} }
// no item is null
if (!nullCount) { return this}
// all items are null
if (nullCount == length) { this.length = 0; return this }
// mix of null // non-null
var idest=0, isrc=length-1;
length -= nullCount ;
while (true) {
// find a non null (source) slot on the right
while (!this[isrc]) { isrc--; nullCount--; }
if (!nullCount) { break } // break if found all null
// find one null slot on the left (destination)
while ( this[idest]) { idest++ }
// perform copy
this[idest]=this[isrc];
if (!(--nullCount)) {break}
idest++; isrc --;
}
this.length=length;
return this;
};
Object.defineProperty(Array.prototype, 'removeNull',
{ value : removeNull, writable : true, configurable : true } ) ;
arr.filter(e => e)
。
smart
的定义——例如动词,以引起剧烈的刺痛。如果我因您的评论而将手机武器化,这与身体疼痛有关。
foo = [0, 1, 2, "", , false, 3, "four", null]
foo.filter(function(e) {
return e === 0 ? '0' : e
})
返回
[0, 1, 2, 3, "four"]
这行得通,我在 AppJet 中对其进行了测试(您可以将代码复制粘贴到它的 IDE 上,然后按“重新加载”以查看它的工作原理,无需创建帐户)
/* appjet:version 0.1 */
function Joes_remove(someArray) {
var newArray = [];
var element;
for( element in someArray){
if(someArray[element]!=undefined ) {
newArray.push(someArray[element]);
}
}
return newArray;
}
var myArray2 = [1,2,,3,,3,,,0,,,4,,4,,5,,6,,,,];
print("Original array:", myArray2);
print("Clenased array:", Joes_remove(myArray2) );
/*
Returns: [1,2,3,3,0,4,4,5,6]
*/
for ... in
枚举键的行为实际上导致跳过丢失的元素。 undefined
的测试仅用于删除显式设置为该值的真实元素。
在(对象成员)循环中“滥用” for ...。 => 只有真值出现在循环体中。
// --- Example ----------
var field = [];
field[0] = 'One';
field[1] = 1;
field[3] = true;
field[5] = 43.68;
field[7] = 'theLastElement';
// --- Example ----------
var originalLength;
// Store the length of the array.
originalLength = field.length;
for (var i in field) {
// Attach the truthy values upon the end of the array.
field.push(field[i]);
}
// Delete the original range within the array so that
// only the new elements are preserved.
field.splice(0, originalLength);
for ... in
的行为是从数组中删除未定义的键,但实际上您在这里没有代码可以仅接受“真实”值
这可能会对您有所帮助:https://lodash.com/docs/4.17.4#remove
var details = [
{
reference: 'ref-1',
description: 'desc-1',
price: 1
}, {
reference: '',
description: '',
price: ''
}, {
reference: 'ref-2',
description: 'desc-2',
price: 200
}, {
reference: 'ref-3',
description: 'desc-3',
price: 3
}, {
reference: '',
description: '',
price: ''
}
];
scope.removeEmptyDetails(details);
expect(details.length).toEqual(3);
scope.removeEmptyDetails = function(details){
_.remove(details, function(detail){
return (_.isEmpty(detail.reference) && _.isEmpty(detail.description) && _.isEmpty(detail.price));
});
};
var data= {
myAction: function(array){
return array.filter(function(el){
return (el !== (undefined || null || ''));
}).join(" ");
}
};
var string = data.myAction(["I", "am","", "working", "", "on","", "nodejs", "" ]);
console.log(string);
输出:
我正在研究nodejs
它将从数组中删除空元素并显示其他元素。
arr = arr.filter(function(n){return n; });
foo.join("").split("")
似乎仅在字符串是单个字符时才有效arr.filter(e=>e)
这可以通过 map、reduce 等链接起来。