我有一个看起来像这样的对象:
var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] }
我想删除空值和空对象(数组和对象),使其看起来像:
{ a: {c: [ {d: 2} ], e: 2 }, i: [ 2 ] }
该函数应删除空值,空对象和空数组。有什么优雅的方法吗?
答案 0 :(得分:0)
这是一个递归清除对象的函数。它将深入遍历所有属性,并删除空值,空数组和空对象:
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
}
答案 1 :(得分:0)
为减少重复代码,一种选择是定义一个函数(我们将其称为itemToBool
),该函数可以确定传递给它的泛型值是真实的还是 somewhere 的递归真实,该值应该是数组还是对象。然后,在传递原始对象的函数(或递归传递对象或数组的函数)中,只要有值需要验证,就可以调用该itemToBool
函数。
对于数组,map
乘itemToBool
,然后filter
乘布尔。对于对象,将对象的reduce
entries
转换为另一个对象:将对象的每个值通过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));
答案 2 :(得分:0)
我们不知道您所说的 clean 是什么意思,但是据我了解,您想删除所有null和空值。此算法很简单:递归检查并删除任何空值/ null值(它们会递归检查)。
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));