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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 10:23:45  来源:igfitidea点击:

remove null values from arrays with splice

javascript

提问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 ... inon Arrays.

不要for ... in在数组上使用。

Do take advantage of higher-order functions like filterand 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 someArrayand 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 filtercall 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 mapfor 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.

现在我们想要从结果的任何元素中删除任何空值,这些元素本身就是数组。我用过mapsomeArray.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 ifis 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;
}