2

我正在尝试创建一个函数来从多维数组中删除空值,但效果不是很好。不穿透到最后一层数组,当两个空值相邻时不移除。

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;
}
4

2 回答 2

7

迭代对象时不要从对象中删除元素。

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

一定要利用高阶函数,如filtermap。试试这个:

function removeEmptyArrayElements(arr) { 
   if (!isArray(arr)) {
      return arr;
   } else {
       return arr.filter( function(elem) { 
          return elem !== null
       } ).map(removeEmptyArrayElements)
   }
}

解释:

“高阶”函数是使用其他函数作为值的函数——要么接受它们作为参数,要么返回它们,或两者兼而有之。在这种情况下,我使用了 Javascript 的 Array 类的两种方法,它们接受一个函数作为参数,并使用它来构建和返回一个新数组。

someArray.filter( function 对 的每个元素)调用functionsomeArray并返回一个新数组,该数组仅包含function返回 true 的元素。我在这种情况下传递的函数是function(elem) { return elem !== null }- 即一个匿名函数,如果元素不为 null,则返回 true。因此,该filter调用的结果是删除了所有空值的原始数组。

现在我们要从结果的任何本身是数组的元素中删除任何空值。我用过mapsomeArray.map( function )还对数组的每个元素调用function,但不是根据这些结果返回其输入的子集,而是返回结果本身。例如,[1,2,3].map(function(x){return x*2})返回数组[2,4,6]。在这种情况下,我们传递的函数是我们正在定义的函数 .. 一个对 . 的递归回调removeEmptyElements

我们确实需要一种方法来停止这种无休止的调用自己的循环,这就是外部if的用途——当调用一个不是数组的元素时,我们只是按原样返回它。

于 2012-05-14T20:14:26.663 回答
2

您正在循环要从中删除的数组。这为您提供了“当两个空值相邻时不删除”错误。“它没有渗透到数组的最后一层”部分可能是因为您没有重新分配obj[key]. 数组是按值复制的,而不是引用的。

我会这样做:

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;
}
于 2012-05-14T20:08:38.167 回答