-3

This code removes all null values from array:

var array = [ 0, 1, null, 2, "", 3, undefined, 3,,,,,, 4,, 4,, 5,, 6,,,, ];

var filtered = array.filter(function (el) {
  return el != null;
});

console.log(filtered);

But when I try this on an array with nested arrays that have null values, the nulls are not removed:

var array = [ [ 1, null, 2 ], [ 3, null, 4 ], [ 5, null, 6 ] ];

var filtered = array.filter(function (el) {
  return el != null;
});

console.log(filtered);

The expected output is:

[ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]

Instead of the actual output:

[ [ 1, null, 2 ], [ 3, null, 4 ], [ 5, null, 6 ] ]

How can I change my example to filter null values from the nested arrays?

  • why index 2? what happens to index 1 of the inner arrays for the result? what is the reason for the nested arrays? – Nina Scholz Nov 22 '18 at 18:59
  • Maybe look to https://stackoverflow.com/a/38132582/6523409. Filter should be called recursively. – Filip Š Nov 22 '18 at 19:01
  • @Nina Scholz, I have a long array with thouthands of rows with null elements inside. I'd like to make it work with every null element, not only for index 1. –  Nov 22 '18 at 19:05
  • i mean, how do you come from the given array with falsy values to the result? – Nina Scholz Nov 22 '18 at 19:06
  • I've edited your question to hopefully clarify for everyone. If I have deviated too far from your original intent, please feel free to roll back my edit via [the revisions page](https://stackoverflow.com/posts/53436773/revisions) –  Nov 22 '18 at 19:47

5 Answers5

3

If your array-of-arrays only has one level, then you can just map it like this:

var filtered = array.map(subarray => subarray.filter(el => el != null));
console.log(filtered);
Pedro LM
  • 742
  • 4
  • 12
  • Good work. This is the only answer that need be considered. This problem is too simple to overengineer with reduce, etc. – Ben Steward Nov 22 '18 at 19:42
1

You need to recursively filter for null, like so:

function removeNull(array) {
  return array
    .filter(item => item !== null)
    .map(item => Array.isArray(item) ? removeNull(item) : item);
}

This function takes an array, and recursively removes all instances of null.

First, I took your solution and wrapped it in a function so that it is able to be called.

Then, after the items are filtered, it's as simple as mapping over the remaining items, checking if each one is an array, and then for each one that is, calling removeNull on it.

EDIT: I had a typo in my code originally, but it should work now.

neonfuz
  • 314
  • 1
  • 4
0
var filterFn = function(item) {
    if (item instanceof Array) {
        // do this if you want to remove empty arrays:
        var items = item.splice(0).filter(filterFn);
        var length = items.length;
        Array.prototype.push.apply(item, items);
        return length;
        // if you want to keep empty arrays do this:
        var items = item.splice(0);
        Array.prototype.push.apply(item, items.filter(filterFn))
        return true;
    }
    return item != null;
};
array = array.filter(filterFn);

This will also work on more than 2 level, as it's recursive.

Frane Poljak
  • 2,315
  • 23
  • 25
  • Frane Poljak, thank you. But it returns an empty array https://playcode.io/156503?tabs=console&script.js&output –  Nov 22 '18 at 19:10
  • You have to choose between two options in the if (...) block, and remove another one. – Frane Poljak Nov 22 '18 at 19:12
0
var arraylist = [0, 1, null, 5];
var i = arraylist.length;
var j =0;
var newlist = [];

while(j < i){

if(arraylist[j] != null){

    newlist.push(arraylist[j]);

}

j++;
}

console.log(newlist);

https://jsfiddle.net/L4nmtg75/

BadPiggie
  • 5,471
  • 1
  • 14
  • 28
0

You're examples remove undefined values as well as null values, and your expected output reflects that, so I'm going to assume that you mean you want to recursively remove both undefined and null values. Your example uses a loose equality comparison which means that it will match both null and undefined. While this works, it is much better to be explicit about what you're checking for with strict equality comparison using ===.

You're going to need to use recursion:

Recursion

An act of a function calling itself. Recursion is used to solve problems that contain smaller sub-problems.

- https://developer.mozilla.org/en-US/docs/Glossary/Recursion

This also means that you're going to want to use Array#reduce instead of Array#filter. Use a new array as the accumulator.

Then for each element in the input array where the element is not null or undefined:

  • if the element is an instance of Array, push the result of calling this function on the element onto the accumulator array,
  • otherwise push the element onto the accumulator array

Return the accumulator array at the end of the reduce callback as the accumulator

const input = [ [ 1, null, 2 ], null,,,,, [ 3, null, 4 ],,,,, [ 5, null, 6 ],,,,, [ 7, [ 8, undefined, 9 ], 10 ] ]

function recursiveValues(input) {
  if(!(input instanceof Array)) return null
  return input.reduce((output, element) => { 
     if(element !== null && element !== undefined) {
        if(element instanceof Array) {
            output.push(recursiveValues(element))
        } else {
            output.push(element)
        }
    }
    return output
  }, [])
}

const output = recursiveValues(input)

console.log(JSON.stringify(output))