Reputation: 6257
I have an array of objects, that can either have direct or nested values. The goal is to remove all empty fields.
For exemple:
const todos = [ {}, { not: {} } ]
// expected output: []
const todos2 = [ {}, { not: {countries: ["uk", "us"]} } ]
// expected output: [{ not: {countries: ["uk", "us"]} }]
I've tried to filter the array with Object.values.length, it when a nested value is an empty object, it doesn't work anymore. Would someone know how to do it?
EDIT: So I've came up with my own solution which is a bit simpler from what I've read here:
function foo(todos){
todos.map((todo,i)=> {
if(!Object.keys(todo).length){
return todos.splice(i, 1)
}
if(Object.keys(todo).length){
const key = Object.keys(todo) + ""
return !Object.values(todo[key]).length && todos.splice(i, 1)
}
return todo
})
return todos.filter(c=> Object.keys(c).length)
}
Upvotes: 0
Views: 1354
Reputation: 4806
try with filter
const isEmpty = e => Object.entries(e).length
const removeEmptyObject = e => e.not?isEmpty(e.not):isEmpty(e)
const todos = [ {}, { not: {} } ]
console.log(todos.filter(removeEmptyObject))
const todos2 = [ {}, { not: {countries: ["uk", "us"]} } ]
console.log(todos2.filter(removeEmptyObject))
Upvotes: -1
Reputation: 24181
Because your structure has a mix of Objects and Arrays, you will want to check for this.
Below is an example.
function trimEmptyObjects(o) {
if (typeof o !== 'object') return o;
if (Array.isArray(o)) {
for (let i = o.length -1; i >= 0; i --) {
o[i] = trimEmptyObjects(o[i]);
if (typeof o[i] === 'object') {
if (!Object.keys(o[i]).length) {
o.splice(i, 1);
}
}
}
return o;
} else {
const e = Object.entries(o);
for (let i = e.length -1; i >= 0; i --) {
e[i][1] = trimEmptyObjects(e[i][1]);
if (typeof e[i][1] === 'object') {
if (!Object.keys(e[i][1]).length) {
e.splice(i, 1);
}
}
}
return Object.fromEntries(e);
}
}
const todos = [ {}, { not: {} } ]
// expected output: []
console.log(trimEmptyObjects(todos));
const todos2 = [ {}, { not: {countries: ["uk", "us"]} } ]
// expected output: [{ not: {countries: ["uk", "us"]} }]
console.log(trimEmptyObjects(todos2));
Upvotes: 1
Reputation: 3730
I think you want like this..
const todos = [ {}, { not: {} } ];
const todos2 = [ {}, { not: {countries: ["uk", "us"]} } ];
function clean(object) {
Object
.entries(object)
.forEach(([k, v]) => {
if (v && typeof v === 'object') {
clean(v);
}
if (v && typeof v === 'object' && !Object.keys(v).length || v === null || v === undefined) {
if (Array.isArray(object)) {
object.splice(k, 1);
} else {
delete object[k];
}
}
});
return object;
}
console.log(clean(todos));
console.log(clean(todos2));
Upvotes: 0