Reputation: 2480
I've got a data array:
const data = [{
name: 'South America',
locations: [{
name: 'Argentina',
locations: [{
name: 'Buenos Aires'
}, {}]
}]
}, {
name: 'Europe',
locations: [{
name: 'Spain',
locations: [{}]
}]
}, {
name: 'Asia',
locations: [{}]
}]
I'd like to remove any empty objects on any level (even if it's really deep). Returning as the example below:
[{
name: 'South America',
locations: [{
name: 'Argentina',
locations: [{
name: 'Buenos Aires'
}]
}]
}, {
name: 'Europe',
locations: [{
name: 'Spain',
locations: []
}]
}, {
name: 'Asia',
locations: []
}]
The key locations
could be anything else.
My solution is just partial as it only deletes the first level.
FAILED ATTEMPT
const result = data.filter(value => Object.keys(value).length !== 0)
I'd like this to be as dynamic as possible, without having to specify how nested will it be.
Upvotes: 1
Views: 804
Reputation: 122037
You could use create a recursive function with reduce
and a for...in
loop and make it so that both empty objects in a array and as a object value are removed.
const data = [{"name":"South America","locations":[{"name":"Argentina","locations":[{"name":"Buenos Aires","foo":{}},{}]}]},{"name":"Europe","locations":[{"name":"Spain","locations":[{}]}]},{"name":"Asia","locations":[{}]}]
function removeEmpty(data) {
return data.reduce((r, e) => {
if (Object.keys(e).length) {
const obj = {}
for (let k in e) {
if (Array.isArray(e[k])) {
obj[k] = removeEmpty(e[k])
} else if (typeof e[k] === 'object') {
if (Object.keys(e[k]).length) {
obj[k] = removeEmpty(e[k])
}
} else {
obj[k] = e[k]
}
}
r.push(obj)
}
return r;
}, [])
}
console.log(removeEmpty(data))
Upvotes: 1
Reputation: 345
const data = [{
name: 'South America',
locations: [{
name: 'Argentina',
locations: [{
name: 'Buenos Aires'
}, {}]
}]
}, {
name: 'Europe',
locations: [{
name: 'Spain',
locations: [{}]
}]
}, {
name: 'Asia',
locations: [{}]
}]
const isArray = Array.isArray
const isObject = (any) => typeof any === 'object' && any !== null
function clear(obj) {
(function recursive(any, remove) {
if (isArray(any)) {
for (let i = 0; i < any.length; ++i) {
recursive(any[i], () => {
any.splice(i--, 1)
})
}
}
else if (isObject(any)) {
const values = Object.values(any)
if (values.length) {
for (let item of values) {
recursive(item, () => null)
}
} else {
remove() // <- delete {}
}
}
})(obj, () => null)
}
//
clear(data)
console.log(data)
Upvotes: 0