Don't remove elements from an object while you are iterating over it.
Don't use for ... in
on Arrays.
Do take advantage of higher-order functions like filter
and map
. Try this:
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.
someArray.filter(
function )
calls function on every element of someArray
and returns a new array containing only the elements for which function returned 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.
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 function on 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
.
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.