Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursively remove undefined from object (including parent)

I'm trying to find a solution to a problem where I need to remove undefined from nested object including all parents if there are no values there, please consider example:

var test = {
  foo : {
    bar : {
      baz : undefined
    }
  },
  bar : 1
}

So my task is to remove baz along with bar and foo but still have bar at the root level; I know that it's trivial task to solve with 2 for loops, I'm just wondering if there are more elegant and clean solutions which will use recursive stack instead? Thanks in advance!

like image 869
Alega Ahafonov Avatar asked Feb 05 '23 12:02

Alega Ahafonov


1 Answers

Depth-first recursion should be able to handle it:

function cleanse(obj, path) {
    Object.keys(obj).forEach(function(key) {
        // Get this value and its type
        var value = obj[key];
        var type = typeof value;
        if (type === "object") {
            // Recurse...
            cleanse(value);
            // ...and remove if now "empty" (NOTE: insert your definition of "empty" here)
            if (!Object.keys(value).length) {
                delete obj[key]
            }
        }
        else if (type === "undefined") {
            // Undefined, remove it
            delete obj[key];
        }
    });
}

Example:

var test = {
  foo : {
    bar : {
      baz : undefined
    }
  },
  bar : 1
};
cleanse(test);
function cleanse(obj, path) {
    Object.keys(obj).forEach(function(key) {
        // Get this value and its type
        var value = obj[key];
        var type = typeof value;
        if (type === "object") {
            // Recurse...
            cleanse(value);
            // ...and remove if now "empty" (NOTE: insert your definition of "empty" here)
            if (!Object.keys(value).length) {
                delete obj[key]
            }
        }
        else if (type === "undefined") {
            // Undefined, remove it
            delete obj[key];
        }
    });
}
console.log(test);

Note that that only visits own, enumerable properties of the objects whose names are not Symbols (ES2015+). If you also want to handle properties inherited from prototypes, or non-enumerable properties, or properties whose names are Symbols, you'll need to adjust to handle that. (You can get non-enumerable properties on an ES5 or later JavaScript engine via getOwnPropertyNames.)

like image 147
T.J. Crowder Avatar answered Feb 07 '23 13:02

T.J. Crowder