How to deep remove all falsey values and empty objects using lodash ?
f.e. I want my object :
{ a:undefined, b:2, c:4, d:undefined , e:{ f:{} , g:null } }
to become:
{ b:2, c:4 };
var test = {
a: undefined,
b: 2,
c: 4,
d: undefined,
e: {
f: {},
g: null
}
};
function clean(obj) {
for (var propName in obj) {
if (_.isObject(obj[propName])) {
clean(obj[propName]);
}
if (obj[propName] === null || obj[propName] === undefined || _.isObject(obj[propName]) && _.isEmpty(obj[propName])) {
delete obj[propName];
}
}
}
clean(test);
console.log(test);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
You could get the properties to delete and get a clean object. This approach mutates to original object.
function clean(value) {
if (value === null || value === undefined) return true;
if (typeof value !== 'object') return false;
if (Array.isArray(value)) {
let i = value.length;
while (i--) if (clean(value[i])) value.splice(i, 1);
return !value.length;
}
Object
.keys(value)
.filter(k => clean(value[k]))
.forEach(Reflect.deleteProperty.bind(null, value));
return !Object.keys(value).length;
}
const
object = { a: undefined, b: 2, c: 4, d: undefined, e: { f: {}, g: null } , h: [], i: [1, []], j: [[[], []]] };
clean(object);
console.log(object);
The question is pretty vague and doesn't specify whether the original structure may or may not be mutated. There is also nothing in there about arrays.
This answer assumes that you don't want to mutate the original data structure and that "deep" also means to go through all array elements. If the object or array results in an empty instance the corresponding key will be removed.
function deepCompact(collection) {
const add = _.isArray(collection)
? (collection, key, value) => collection.push(value)
: (collection, key, value) => collection[key] = value;
return _.transform(collection, (collection, value, key) => {
if (_.isObject(value)) {
value = deepCompact(value);
if (_.isEmpty(value)) return;
} else {
if (!value) return;
}
add(collection, key, value);
});
}
const data1 = {a: undefined, b: 2, c: 4, d: undefined, e: {f: {} , g: null}};
console.log(deepCompact(data1));
const data2 = [{a: 0, b: 2}, false, {c: [{d: null}]}, {e: [{f: 1}]}];
console.log(deepCompact(data2));
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
transform is comparable to reduce, however the first callback parameter is locked to the provided or default accumulator. This means you don't have to return the accumulator from the callback. The default accumulator of transform also differs from reduce. reduce uses the first element as the initial value, whereas transform uses a new object with the same prototype as the provided collection as the default value.
e:{ f:'somevalue , g:null }{}is not falsy.for .. ofloop not work here? Then use an if and delete false properties?