Reputation: 1795
i have one array of object
need to remove empty array KEYS from that, which is nested
here is the sample of array of object
need to remove every fieldGroup array which is empty, with nested level
how can i remove that using LODASH or omit-deep-lodash or any third party library
[
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2EC",
"display_name": "test name",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"id": "dslogo",
"fieldGroup": [] // need to remove all fieldGroup array which is empty array
},
{
"key": "label",
"fieldGroup": []
},
{
"key": "forgotpassword",
"fieldGroup": [ // need which has length
{
"id": "forgotpassword",
"key": "forgotpassword",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end",
"templateOptions": {
"label": "Need help?",
"className": "pull-right",
"hideRequiredMarker": true
},
"_id": "62b4665e9bba345e1937f669"
}
]
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
},
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2ED",
"display_name": "test name 2",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"key": "forgotpassword",
"fieldGroup": [
{
"id": "forgotpassword 11",
"key": "forgotpassword 11",
"type": "link 11"
},
{
"id": "forgotpassword 22",
"key": "forgotpassword 22",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end"
}
]
},
{
"id": "dslogo",
"fieldGroup": []
},
{
"key": "label",
"fieldGroup": []
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
}
]
how can i remove nested level empty array using lodash?
Upvotes: 0
Views: 1150
Reputation: 70
One line code solution similar to Cristian's answer, in case you need to deal with {"fieldGroup": Null}.
const cleanEmptyObj = JSON.parse(JSON.stringify(data, (key, value) => {
if (key === null || value=== "" ||Object.keys(value || {}).length === 0) return undefined;
return value;
}));
const data= [
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2EC",
"display_name": "test name",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"id": "dslogo",
"fieldGroup": [] // need to remove all fieldGroup array which is empty array
},
{
"key": "label",
"fieldGroup": []
},
{
"key": "forgotpassword",
"fieldGroup": [ // need which has length
{
"id": "forgotpassword",
"key": "forgotpassword",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end",
"templateOptions": {
"label": "Need help?",
"className": "pull-right",
"hideRequiredMarker": true
},
"_id": "62b4665e9bba345e1937f669"
}
]
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
},
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2ED",
"display_name": "test name 2",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"key": "forgotpassword",
"fieldGroup": [
{
"id": "forgotpassword 11",
"key": "forgotpassword 11",
"type": "link 11"
},
{
"id": "forgotpassword 22",
"key": "forgotpassword 22",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end"
}
]
},
{
"id": "dslogo",
"fieldGroup": []
},
{
"key": "label",
"fieldGroup": [ {
"id": "dslogo",
"fieldGroup": null
} ]
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
}
]
const cleanEmptyObj = JSON.parse(JSON.stringify(data, (key, value) => {
if (key === null || value=== "" ||Object.keys(value || {}).length === 0) return undefined;
return value;
}));
console.log(cleanEmptyObj);
Upvotes: 0
Reputation: 1
Here is a generic implementation to omit any field with empty array as value from a nested object or array of objects
const data= [
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2EC",
"display_name": "test name",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"id": "dslogo",
"fieldGroup": [] // need to remove all fieldGroup array which is empty array
},
{
"key": "label",
"fieldGroup": []
},
{
"key": "forgotpassword",
"fieldGroup": [ // need which has length
{
"id": "forgotpassword",
"key": "forgotpassword",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end",
"templateOptions": {
"label": "Need help?",
"className": "pull-right",
"hideRequiredMarker": true
},
"_id": "62b4665e9bba345e1937f669"
}
]
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
},
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2ED",
"display_name": "test name 2",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"key": "forgotpassword",
"fieldGroup": [
{
"id": "forgotpassword 11",
"key": "forgotpassword 11",
"type": "link 11"
},
{
"id": "forgotpassword 22",
"key": "forgotpassword 22",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end"
}
]
},
{
"id": "dslogo",
"fieldGroup": []
},
{
"key": "label",
"fieldGroup": []
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
}
]
const deleteFieldIfExistsAndEmpty = (item,fieldToDelete)=>{
if(item.hasOwnProperty(fieldToDelete) && Array.isArray(item[fieldToDelete]) && item[fieldToDelete].length===0){
delete item[fieldToDelete]
}
Object.values(item).forEach((value)=>{
if (
typeof value === 'object' &&
!Array.isArray(value) &&
value !== null
) {
deleteFieldIfExistsAndEmpty(value,fieldToDelete)
} else if(Array.isArray(value)){
omit_deep(value,fieldToDelete)
}
})
}
const omit_deep =(objectData,fieldToDelete)=>{
if(Array.isArray(objectData)){
objectData.forEach(item=>{
deleteFieldIfExistsAndEmpty(item,fieldToDelete)
})
} else if (
typeof objectData === 'object' &&
!Array.isArray(objectData) &&
objectData !== null
) {
deleteFieldIfExistsAndEmpty(objectData,fieldToDelete)
}
}
omit_deep(data,"fieldGroup")
console.log(data)
Upvotes: 0
Reputation: 10414
First, I wouldn't advise you to use any external library. External libraries contain code that you could write as well, just written by other people, and while it would be a good idea to don't re-invent the wheel, it's not for granted that they will do exactly what you need, or that a function is provided for any need.
If performance is a concern, I would advise using JSON.stringify
, since it's natively implemented by most browsers and won't require you to iterate over every node of your object explicitly.
The solution provided by holydragon is acceptable, but it won't guarantee you that if you have a string containing ,"fieldGroup":[]
it won't be replaced as well. This could introduce bugs, even remotely.
Luckily, the function JSON.stringify
contains an overload, it allows you to define a replacer in the second parameter. The replacer enables you to specify some logic about which node should and should not be included in the stringification process.
Said this, you can easily and performantly solve your problem like this:
obj = JSON.parse(JSON.stringify(obj, (key, value) => {
if (key === 'fieldGroup' && JSON.stringify(value) === '[]') return undefined;
return value;
}));
Example:
const obj = [
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2EC",
"display_name": "test name",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"id": "dslogo",
"fieldGroup": [] // need to remove all fieldGroup array which is empty array
},
{
"key": "label",
"fieldGroup": []
},
{
"key": "forgotpassword",
"fieldGroup": [ // need which has length
{
"id": "forgotpassword",
"key": "forgotpassword",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end",
"templateOptions": {
"label": "Need help?",
"className": "pull-right",
"hideRequiredMarker": true
},
"_id": "62b4665e9bba345e1937f669"
}
]
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
},
{
"id": "sch_CV8e5NzZXwXhNp3TGnpryEmub2ED",
"display_name": "test name 2",
"connection_profile": {
"type": "NAVIGATION",
"access_methods": [
{
"submit": true,
"ui_web": [
{
"key": "forgotpassword",
"fieldGroup": [
{
"id": "forgotpassword 11",
"key": "forgotpassword 11",
"type": "link 11"
},
{
"id": "forgotpassword 22",
"key": "forgotpassword 22",
"type": "link",
"className": "d-flex flex-grow-1 justify-content-end"
}
]
},
{
"id": "dslogo",
"fieldGroup": []
},
{
"key": "label",
"fieldGroup": []
}
],
"navigator_method": "login",
"_id": "62b4665e9bba345e1937f663"
}
]
}
}
];
const cleanObj = JSON.parse(JSON.stringify(obj, (key, value) => {
if (key === 'fieldGroup' && JSON.stringify(value) === '[]') return undefined;
return value;
}));
console.log('Before: ', obj);
console.log('After: ', cleanObj);
Note: This solution will only work if the object has not a prototype, or a function attached. In other words, it will only work if the object is stringificable
Upvotes: 1
Reputation: 6728
This solution is short and easy to understand. Please try if it works for you performance-wise.
Concept
fieldGroup
keys that have empty array using replaceAll().Code
const data=[{id:"sch_CV8e5NzZXwXhNp3TGnpryEmub2EC",display_name:"test name",connection_profile:{type:"NAVIGATION",access_methods:[{submit:!0,ui_web:[{id:"dslogo",fieldGroup:[]},{key:"label",fieldGroup:[]},{key:"forgotpassword",fieldGroup:[{id:"forgotpassword",key:"forgotpassword",type:"link",className:"d-flex flex-grow-1 justify-content-end",templateOptions:{label:"Need help?",className:"pull-right",hideRequiredMarker:!0},"_id":"62b4665e9bba345e1937f669"}]}],navigator_method:"login","_id":"62b4665e9bba345e1937f663"}]}},{id:"sch_CV8e5NzZXwXhNp3TGnpryEmub2ED",display_name:"test name 2",connection_profile:{type:"NAVIGATION",access_methods:[{submit:!0,ui_web:[{key:"forgotpassword",fieldGroup:[{id:"forgotpassword 11",key:"forgotpassword 11",type:"link 11"},{id:"forgotpassword 22",key:"forgotpassword 22",type:"link",className:"d-flex flex-grow-1 justify-content-end"}]},{id:"dslogo",fieldGroup:[]},{key:"label",fieldGroup:[]}],navigator_method:"login","_id":"62b4665e9bba345e1937f663"}]}}];
let result = JSON.stringify(data);
result = result.replaceAll(',"fieldGroup":[]','');
result = JSON.parse(result);
console.log(result);
Upvotes: 0
Reputation: 187
method to remove keys with empty array in deep nested objects []
function cleanObj(obj){
function empty(e) {
return Array.isArray(e) && e?.length == 0
}
if(typeof obj === "object"){
Object.entries(obj).forEach(([k,v]) => {
if (empty(v)){
console.log(k,v)
delete obj[k]
} else if( typeof obj[k] === "object" ){
cleanObj(obj[k])
}
})
} else if (Array.isArray(obj)){
for( let i = 0; i < obj.length; i++){
cleanObj(obj[i])
}
}
return obj
}
let cleaned = cleanObj(obj); // return obj without all keys that have [] as value
Upvotes: 0
Reputation: 14171
Why don't you just create a recursive function that walks the entire object and deletes entries when it finds fieldGroup
as an empty array. Something like this:
let removeEmpty = (obj, key) => {
if (!obj) {
return
}
if (Array.isArray(obj)) {
for( let i = 0; i<obj.length; i++) {
removeEmpty(obj[i], key)
}
}
if (typeof obj === "object") {
if (obj[key]?.length === 0) {
delete obj[key]
return
}
const keys = Object.keys(obj);
for (let i = 0; i<keys.length; i++) {
removeEmpty(obj[keys[i]], key)
}
}
}
Then you can call the function like this:
removeEmpty(object, "fieldGroup ")
Notes:
fieldGroup
is an array, if you need this you can add an extra isArray(obj[key])
Upvotes: 1
Reputation: 648
you don't need any lib for this, try this snippet for your desire output.
const newData = data.map(({connection_profile, ...rest}) => {
if (connection_profile && connection_profile?.access_methods?.constructor === Array) {
connection_profile.access_methods.forEach(m => m.ui_web = m.ui_web.filter(f => f.fieldGroup.length))
}
return {
...rest,
connection_profile
}
})
Upvotes: 0
Reputation: 1675
First of all, you don't need a library for this task. I've adapted this solution to work for your use case. The function removeEmptyFieldGroup
filters empty fieldGroup
arrays, builds a new object and repeats the process recursively for nested objects.
const removeEmptyFieldGroup = (obj) => {
return Object.entries(obj)
.filter(([k, v]) => {
if (k !== "fieldGroup") return true;
if (!Array.isArray(v)) return true;
return v.length > 0;
})
.reduce(
(acc, [k, v]) => ({
...acc,
[k]: v === Object(v) ? removeEmptyFieldGroup(v) : v,
}),
{}
);
};
const dataCleaned = removeEmptyFieldGroup(data);
Another solution would be to use the package flat
to flatten the object, evaluate if values of keys ending with fieldGroup
are empty arrays and delete them.
const dataFlat = flatten(data);
Object.keys(dataFlat).forEach((key) => {
if (!key.endsWith("fieldGroup")) return;
if (Array.isArray(dataFlat[key]) && dataFlat[key].length === 0)
delete dataFlat[key];
});
const dataCleaned = unflatten(dataFlat);
Upvotes: 0