javascript 使用 splice 从数组中删除空值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10590257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
remove null values from arrays with splice
提问by 1252748
I'm trying to make a function to remove null values from multidimensional arrays, but it doesn't work very well. It does not penetrate to the last layer of arrays, and does not remove when two null values are adjacent.
我正在尝试创建一个函数来从多维数组中删除空值,但效果不佳。不渗透到最后一层数组,两个空值相邻时不去除。
function isArray(obj) {
// http://stackoverflow.com/a/1058753/1252748
return Object.prototype.toString.call(obj) === '[object Array]';
}
function removeEmptyArrayElements(obj) {
for (key in obj) {
if (obj[key] === null) {
obj = obj.splice(key, 1);
}
var isArr = isArray(obj[key]);
if (isArr) {
removeEmptyArrayElements(obj[key]);
}
}
return obj;
}
回答by Mark Reed
Don't remove elements from an object while you are iterating over it.
在迭代对象时不要从对象中删除元素。
Don't use for ... in
on Arrays.
不要for ... in
在数组上使用。
Do take advantage of higher-order functions like filter
and map
. Try this:
一定要利用像filter
和这样的高阶函数map
。试试这个:
function removeEmptyArrayElements(arr) {
if (!isArray(arr)) {
return arr;
} else {
return arr.filter( function(elem) {
return elem !== null
} ).map(removeEmptyArrayElements)
}
}
Explanation:
解释:
"Higher-order" functions are functions that use other functions as values - either accepting them as parameters, or returning them, or both. In this case I used two methods of Javascript's Array class which accept a function as a parameter and use it to build and return a new array.
“高阶”函数是使用其他函数作为值的函数——要么接受它们作为参数,要么返回它们,或者两者兼而有之。在这种情况下,我使用了 Javascript 的 Array 类的两种方法,它们接受一个函数作为参数并使用它来构建和返回一个新数组。
someArray.filter(
function)
calls functionon every element of someArray
and returns a new array containing only the elements for which functionreturned true. The function I passed in this case is function(elem) { return elem !== null }
- that is, an anonymous function that returns true if the element is not null. So the result of that filter
call is the original array with all the nulls removed.
someArray.filter(
函数对 的每个元素)
调用函数someArray
并返回一个新数组,该数组仅包含函数返回true的元素。我在这种情况下传递的函数是function(elem) { return elem !== null }
- 也就是说,如果元素不为空,则返回 true 的匿名函数。因此,该filter
调用的结果是删除了所有空值的原始数组。
Now we want to remove any nulls from any elements of the result that are themselves arrays. I used map
for that. someArray.map(
function)
also calls functionon every element of the array, but instead of returning a subset of its input based on those results, it just returns the results themselves. For example, [1,2,3].map(function(x){return x*2})
returns the array [2,4,6]
. In this case, the function we pass is the one we're in the middle of defining .. a recursive call back to removeEmptyElements
.
现在我们想要从结果的任何元素中删除任何空值,这些元素本身就是数组。我用过map
。someArray.map(
function)
还对数组的每个元素调用function,但它不是根据这些结果返回其输入的子集,而是仅返回结果本身。例如,[1,2,3].map(function(x){return x*2})
返回数组[2,4,6]
。在这种情况下,我们传递的函数是我们正在定义 .. 递归调用的函数removeEmptyElements
。
We do need a way to stop this endless cycle of calling ourselves, and that's what the outer if
is for - when called on an element that isn't an array, we just return it as-is.
我们确实需要一种方法来停止这种无休止的调用自己的循环,这就是外部if
的用途——当调用一个不是数组的元素时,我们只是按原样返回它。
回答by Halcyon
You're looping over an array you are deleting from. This gives you the "does not remove when two null values are adjacent"bug. The "It does not penetrate to the last layer of arrays"part is probably because you're not reassigning the value at obj[key]
. Arrays are copied by value, not referenced.
您正在遍历要从中删除的数组。这会给您“当两个空值相邻时不删除”错误。该“它不会渗透到阵列的最后一层”一部分可能是因为你不重新分配的值obj[key]
。数组是按值复制的,而不是引用。
I'd do it like this:
我会这样做:
function isArray(obj) {
// http://stackoverflow.com/a/1058753/1252748
return Object.prototype.toString.call(obj) === '[object Array]';
}
function removeEmptyArrayElements(arr) {
var i;
for (i = 0; i < arr.length; i += 1) {
if (arr[i] === null) {
arr = arr.splice(i, 1);
i -= 1; // decrement counter!
} else if (isArray(arr[i])) {
arr[i] = removeEmptyArrayElements(arr[i]);
}
}
return arr;
}