繁体   English   中英

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

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

我有一个看起来像这样的对象:

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

我想删除空值和空对象(数组和对象),使其看起来像:

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

该函数应该删除空值,空对象和空数组。 有什么优雅的方式吗?

这是一个递归清理对象的函数。 它将遍历所有属性并删除空值,空数组和空对象:

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
}

为了减少重复代码,一个选项是定义一个函数(让我们称之为itemToBool ),该函数可以确定传递给它的泛型值是真的,还是递归地在某个地方 ,如果值是数组或对象。 然后,在传递原始对象的函数中(或者,递归地传递一个对象或数组),只要有值要验证,就可以调用该itemToBool函数。

在数组的情况下,按itemToBool map ,然后按布尔filter 在对象的情况下,将对象的entries reduce到另一个对象:通过itemToBool传递对象的每个值以递归地转换它(如果值是数组或对象),并且如果转换的值具有任何键(或者是一个真实的原语),将它分配给累加器。 无需依赖图书馆:

 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)); 

嗯...你也可以抽象检查键的数量到一个函数:

 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)); 

我们不清楚你的意思是干净 ,但据我所知,你想要删除所有空值和空值。 此算法是直接的: 递归检查并删除任何空/空值(以递归方式检查)。

 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