从对象中移除空对象
Remove empty objects from an object
我正在尝试删除对象内的空对象,这是一个具有预期输出的示例:
var object = {
a: {
b: 1,
c: {
a: 1,
d: {},
e: {
f: {}
}
}
},
b: {}
}
var expectedResult = {
a: {
b: 1,
c: {
a: 1,
}
}
}
我尝试使用其他 Whosebug 问题中的一些示例,但这些仅适用于一级对象。
function clean(obj) {
for (var propName in obj) {
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName]; }
}
}
编辑:
function clean(obj) {
for (var propName in obj) {
if(typeof obj[propName]=="object")
clean(obj[propName])
if (obj[propName] === null || obj[propName] === undefined)
delete obj[propName];
}
}
去除空对象的基本功能
首先从一个只适用于单层嵌套的函数开始。
此函数删除所有引用空对象的属性:
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue // If null or not an object, skip to the next iteration
}
// The property is an object
if (Object.keys(o[k]).length === 0) {
delete o[k]; // The object had no properties, so delete that property
}
return o;
}
}
使用递归处理嵌套对象
现在您想使它递归,以便它可以对嵌套对象进行操作。所以我们已经测试了 o[k]
是否是一个对象,并且我们已经测试了是否有属性,所以如果有,我们只需使用该嵌套对象再次调用该函数。
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue // If null or not an object, skip to the next iteration
}
// The property is an object
clearEmpties(o[k]); // <-- Make a recursive call on the nested object
if (Object.keys(o[k]).length === 0) {
delete o[k]; // The object had no properties, so delete that property
}
}
return o;
}
因此,正如对 clearEmpties
的原始调用会删除引用空对象的给定对象的属性一样,递归调用也会对嵌套对象执行相同的操作。
现场演示:
var object = {
a: {
b: 1,
c: {
a: 1,
d: {},
e: { // will need to be removed after f has been removed
f: {}
}
}
},
b: {}
};
clearEmpties(object);
console.log(object);
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue
}
clearEmpties(o[k]);
if (Object.keys(o[k]).length === 0) {
delete o[k];
}
}
return o;
}
使用下划线和函数式样式的简短版本
function clearEmpties(o) {
if (_.isFunction(o) || !_.isObject(o)) return o;
return _.chain(o)
.mapObject(clearEmpties)
.pick(p => !(_.isObject(p) && _.isEmpty(p)))
.value();
}
使用 lodash 和函数式风格的简短版本 - 适用于 treeshaking
import { isFunction, isObject, isEmpty, isArray, isPlainObject, fromPairs } from "lodash-es";
const removeEmtpyObjects = (o) => {
if (isFunction(o) || !isPlainObject(o)) return o;
if (isArray(o)) return o.map(removeEmtpyObjects);
return fromPairs(
Object.entries(o)
.map(([k, v]) => [k, removeEmtpyObjects(v)])
.filter(([k, v]) => !(v == null || (isObject(v) && isEmpty(v))))
);
};
我遇到了同样的问题,而且我的对象可能包含包含空元素的数组,这些元素也需要删除。
我最终得到了这个快速而肮脏的解决方案。
如果你想定义“空”对你意味着什么,我还添加了一个不同的功能。就我而言,我还需要空字符串。
function isEmpty(obj) {
if (obj === '' || obj === null || JSON.stringify(obj) === '{}' || JSON.stringify(obj) === '[]' || (obj) === undefined || (obj) === {}) {
return true
} else {
return false
}
}
function removeEmpty(o) {
if (typeof o !== "object") {
return o;
}
let oKeys = Object.keys(o)
for (let j = 0; j < oKeys.length; j++) {
let p = oKeys[j]
switch (typeof (o[p])) {
case 'object':
if (Array.isArray(o[p])) {
for (let i = 0; i < o[p].length; i++) {
o[p][i] = removeEmpty(o[p][i])
if (isEmpty(o[p][i])) {
o[p].splice(i, 1)
i--
}
}
if (o[p].length === 0) {
if (Array.isArray(o)) {
o.splice(parseInt(p), 1)
j--
} else {
delete o[p]
}
}
} else {
if (isEmpty(o[p])) {
delete o[p]
} else {
o[p] = removeEmpty(o[p])
if (isEmpty(o[p])) {
delete o[p]
}
}
}
break
default:
if (isEmpty(o[p])) {
delete o[p]
}
break
}
}
if (Object.keys(o).length === 0) {
return
}
return o
}
输入:
var a = {
b: 1,
c: {
d: [1, [[], [], [[[1], []]]], [2, [[], [[]]]], [], [[]]]
},
e: {
f: [{}, { g: 1 }]
},
h: {
i: { j: { k: undefined, l: null, m: { n: "", o: 1 } } }
},
p: { q: { r: 1 } }
}
removeEmpty(a)
输出:
{
"b": 1,
"c": {
"d": [1, [[[[1]]]], [2]]
},
"e": {
"f": [{"g": 1}]
},
"h": {
"i": {
"j": {
"m": {
"o": 1
}
}
}
},
"p": {
"q": {
"r": 1
}
}
}
我正在尝试删除对象内的空对象,这是一个具有预期输出的示例:
var object = {
a: {
b: 1,
c: {
a: 1,
d: {},
e: {
f: {}
}
}
},
b: {}
}
var expectedResult = {
a: {
b: 1,
c: {
a: 1,
}
}
}
我尝试使用其他 Whosebug 问题中的一些示例,但这些仅适用于一级对象。
function clean(obj) {
for (var propName in obj) {
if (obj[propName] === null || obj[propName] === undefined) {
delete obj[propName]; }
}
}
编辑:
function clean(obj) {
for (var propName in obj) {
if(typeof obj[propName]=="object")
clean(obj[propName])
if (obj[propName] === null || obj[propName] === undefined)
delete obj[propName];
}
}
去除空对象的基本功能
首先从一个只适用于单层嵌套的函数开始。
此函数删除所有引用空对象的属性:
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue // If null or not an object, skip to the next iteration
}
// The property is an object
if (Object.keys(o[k]).length === 0) {
delete o[k]; // The object had no properties, so delete that property
}
return o;
}
}
使用递归处理嵌套对象
现在您想使它递归,以便它可以对嵌套对象进行操作。所以我们已经测试了 o[k]
是否是一个对象,并且我们已经测试了是否有属性,所以如果有,我们只需使用该嵌套对象再次调用该函数。
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue // If null or not an object, skip to the next iteration
}
// The property is an object
clearEmpties(o[k]); // <-- Make a recursive call on the nested object
if (Object.keys(o[k]).length === 0) {
delete o[k]; // The object had no properties, so delete that property
}
}
return o;
}
因此,正如对 clearEmpties
的原始调用会删除引用空对象的给定对象的属性一样,递归调用也会对嵌套对象执行相同的操作。
现场演示:
var object = {
a: {
b: 1,
c: {
a: 1,
d: {},
e: { // will need to be removed after f has been removed
f: {}
}
}
},
b: {}
};
clearEmpties(object);
console.log(object);
function clearEmpties(o) {
for (var k in o) {
if (!o[k] || typeof o[k] !== "object") {
continue
}
clearEmpties(o[k]);
if (Object.keys(o[k]).length === 0) {
delete o[k];
}
}
return o;
}
使用下划线和函数式样式的简短版本
function clearEmpties(o) {
if (_.isFunction(o) || !_.isObject(o)) return o;
return _.chain(o)
.mapObject(clearEmpties)
.pick(p => !(_.isObject(p) && _.isEmpty(p)))
.value();
}
使用 lodash 和函数式风格的简短版本 - 适用于 treeshaking
import { isFunction, isObject, isEmpty, isArray, isPlainObject, fromPairs } from "lodash-es";
const removeEmtpyObjects = (o) => {
if (isFunction(o) || !isPlainObject(o)) return o;
if (isArray(o)) return o.map(removeEmtpyObjects);
return fromPairs(
Object.entries(o)
.map(([k, v]) => [k, removeEmtpyObjects(v)])
.filter(([k, v]) => !(v == null || (isObject(v) && isEmpty(v))))
);
};
我遇到了同样的问题,而且我的对象可能包含包含空元素的数组,这些元素也需要删除。
我最终得到了这个快速而肮脏的解决方案。
如果你想定义“空”对你意味着什么,我还添加了一个不同的功能。就我而言,我还需要空字符串。
function isEmpty(obj) {
if (obj === '' || obj === null || JSON.stringify(obj) === '{}' || JSON.stringify(obj) === '[]' || (obj) === undefined || (obj) === {}) {
return true
} else {
return false
}
}
function removeEmpty(o) {
if (typeof o !== "object") {
return o;
}
let oKeys = Object.keys(o)
for (let j = 0; j < oKeys.length; j++) {
let p = oKeys[j]
switch (typeof (o[p])) {
case 'object':
if (Array.isArray(o[p])) {
for (let i = 0; i < o[p].length; i++) {
o[p][i] = removeEmpty(o[p][i])
if (isEmpty(o[p][i])) {
o[p].splice(i, 1)
i--
}
}
if (o[p].length === 0) {
if (Array.isArray(o)) {
o.splice(parseInt(p), 1)
j--
} else {
delete o[p]
}
}
} else {
if (isEmpty(o[p])) {
delete o[p]
} else {
o[p] = removeEmpty(o[p])
if (isEmpty(o[p])) {
delete o[p]
}
}
}
break
default:
if (isEmpty(o[p])) {
delete o[p]
}
break
}
}
if (Object.keys(o).length === 0) {
return
}
return o
}
输入:
var a = {
b: 1,
c: {
d: [1, [[], [], [[[1], []]]], [2, [[], [[]]]], [], [[]]]
},
e: {
f: [{}, { g: 1 }]
},
h: {
i: { j: { k: undefined, l: null, m: { n: "", o: 1 } } }
},
p: { q: { r: 1 } }
}
removeEmpty(a)
输出:
{
"b": 1,
"c": {
"d": [1, [[[[1]]]], [2]]
},
"e": {
"f": [{"g": 1}]
},
"h": {
"i": {
"j": {
"m": {
"o": 1
}
}
}
},
"p": {
"q": {
"r": 1
}
}
}