简体   繁体   English

如何从对象中深度删除空值,空对象和空数组

[英]How to deeply remove null values, empty objects and empty array from an object

I have an object that looks like this: 我有一个看起来像这样的对象:

var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] }

I want to remove null values and and empty objects (array and objects) so that it looks like: 我想删除空值和空对象(数组和对象),使其看起来像:

{ a: {c: [ {d: 2} ], e: 2 }, i: [ 2 ] }

The function should remove null values, empty objects and empty arrays. 该函数应该删除空值,空对象和空数组。 Any elegant way to do it ? 有什么优雅的方式吗?

Here is a function that clean the object recursively. 这是一个递归清理对象的函数。 It will loop deeply through all the properties and remove null values, null arrays and null objects: 它将遍历所有属性并删除空值,空数组和空对象:

cleanUpObject(jsonObject: object): object {

    Object.keys(jsonObject).forEach(function (key, index) {
        const currentObj = jsonObject[key]

        if (_.isNull(currentObj)) {
            delete jsonObject[key]
        } else if (_.isObject(currentObj)) {
            if (_.isArray(currentObj)) {
                if (!currentObj.length) {
                    delete jsonObject[key]
                } else {
                    const cleanupArrayObj = []
                    for (const obj of currentObj) {
                        if (!_.isNull(obj)) {
                            const cleanObj = this.cleanUpJson(obj)
                            if (!_.isEmpty(cleanObj)) {
                                cleanupArrayObj.push(cleanObj)
                            }
                        }
                    }
                    if (!cleanupArrayObj.length) {
                        delete jsonObject[key]
                    } else {
                        jsonObject[key] = cleanupArrayObj
                    }
                }
            } else {
                if (_.isEmpty(Object.keys(jsonObject[key]))) {
                    delete jsonObject[key]
                } else {
                    jsonObject[key] = this.cleanUpJson(currentObj)

                    if (_.isEmpty(Object.keys(jsonObject[key]))) {
                        delete jsonObject[key]
                    }
                }
            }
        }
    }, this)

    return jsonObject
}

To reduce repetitive code, one option is to define a function (let's call it itemToBool ) that can determine whether a generic value passed to it is truthy, or recursively truthy somewhere , should the value be an array or object. 为了减少重复代码,一个选项是定义一个函数(让我们称之为itemToBool ),该函数可以确定传递给它的泛型值是真的,还是递归地在某个地方 ,如果值是数组或对象。 Then, in the function that gets passed the original object (or, gets recursively passed an object or array), you can call that itemToBool function whenever there's a value to validate. 然后,在传递原始对象的函数中(或者,递归地传递一个对象或数组),只要有值要验证,就可以调用该itemToBool函数。

In the case of arrays, map by itemToBool and then filter by Boolean. 在数组的情况下,按itemToBool map ,然后按布尔filter In the case of objects, reduce the entries of the object into another object: pass each value of the object through itemToBool to recursively transform it (in case the value is an array or object), and if the transformed value has any keys (or is a truthy primitive), assign it to the accumulator. 在对象的情况下,将对象的entries reduce到另一个对象:通过itemToBool传递对象的每个值以递归地转换它(如果值是数组或对象),并且如果转换的值具有任何键(或者是一个真实的原语),将它分配给累加器。 No need to depend a library: 无需依赖图书馆:

 var myObject = { a: { b: [{}], c: [{}, { d: 2 }], e: 2, f: {} }, g: {}, h: [], i: [null, 2] }; // Returns a falsey value if the item is falsey, // or if the deep cleaned array or object is empty: const itemToBool = item => { if (typeof item !== 'object' || item === null) return item; const cleanedItem = clean(item); return Object.keys(cleanedItem).length !== 0 && cleanedItem; }; const clean = obj => { if (Array.isArray(obj)) { const newArr = obj.map(itemToBool).filter(Boolean); return newArr.length && newArr; } const newObj = Object.entries(obj).reduce((a, [key, val]) => { const newVal = itemToBool(val); if (newVal) a[key] = newVal; return a; }, {}); return Object.keys(newObj).length > 0 && newObj; }; console.log(clean(myObject)); 

Hmm... you also might abstract the check of the number of keys into a function as well: 嗯...你也可以抽象检查键的数量到一个函数:

 var myObject={a:{b:[{}],c:[{},{d:2}],e:2,f:{}},g:{},h:[],i:[null,2]} // Returns the object / array if it has at least one key, else returns false: const validObj = obj => Object.keys(obj).length && obj; const itemToBool = item => ( typeof item !== 'object' || item === null ? item : validObj(clean(item)) ); const clean = obj => validObj( Array.isArray(obj) ? obj.map(itemToBool).filter(Boolean) : Object.entries(obj).reduce((a, [key, val]) => { const newVal = itemToBool(val); if (newVal) a[key] = newVal; return a; }, {}) ); console.log(clean(myObject)); 

We don't know what you mean by clean , but from what I understand, you want to remove all null and empty values. 我们不清楚你的意思是干净 ,但据我所知,你想要删除所有空值和空值。 This algorithm is straight-forward: recursively check for and remove any empty / null values (which are recursively checked). 此算法是直接的: 递归检查并删除任何空/空值(以递归方式检查)。

 function clean(obj) { // clean array if (Array.isArray(obj)) { for (let i=0; i<obj.length; i++) { if (isNothing(obj[i])) obj.splice(i, 1); // remove value if falsy else if (typeof obj[i] === 'object') clean(obj[i]); // recurse if it's a truthy object } // clean other object } else { for (let prop in obj) { if (!obj.hasOwnProperty(prop)) continue; if (isNothing(obj[prop])) delete obj[prop]; // remove value if falsy else if (typeof obj[prop] === 'object') clean(obj[prop]); // recurse if it's a truthy object } } } // Recursively check for populated or nonnull content. If none found, return `true`. Recursive so [{}] will be treated as empty. function isNothing(item) { // null / undefined if (item == null) return true; // deep object falsiness if (typeof item === 'object') { if (Array.isArray(item)) { // array -> check for populated/nonnull value for (let i=0; i<item.length; i++) { if (!isNothing(item[i])) return false; } return true; } // other object -> check for populated/nonnull value for (let prop in item) { if (!item.hasOwnProperty(prop)) continue; if (!isNothing(item[prop])) return false; } return true; } return false; } var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] }; console.log("Before: " + JSON.stringify(myObject)); clean(myObject); console.log("After: " + JSON.stringify(myObject)); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM