Apurv Chaudhary
Apurv Chaudhary

Reputation: 1795

Remove all empty array from array of object using lodash or omit-deep-lodash

  1. i have one array of object

  2. need to remove empty array KEYS from that, which is nested

  3. here is the sample of array of object

  4. need to remove every fieldGroup array which is empty, with nested level

  5. 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

Answers (8)

Aiden Or
Aiden Or

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

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

Christian Vincenzo Traina
Christian Vincenzo Traina

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

holydragon
holydragon

Reputation: 6728

This solution is short and easy to understand. Please try if it works for you performance-wise.

Concept

  1. Convert the whole array into a string using JSON.stringify().
  2. Replace all of the string in JSON format for the fieldGroup keys that have empty array using replaceAll().
  3. Convert the string back to array using JSON.parse().

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

araldhafeeri
araldhafeeri

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

Radu Diță
Radu Diță

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:

  • This will modify the original object
  • It doesn't check that fieldGroup is an array, if you need this you can add an extra isArray(obj[key])

Upvotes: 1

Mohit Sharma
Mohit Sharma

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

alexanderdavide
alexanderdavide

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

Related Questions