我有一个具有多个属性的对象,我想使用 lodash 删除空的对象/嵌套对象。最好的方法是什么?
Let template = {
node: "test",
representation: {
range: { }
},
transmit: {
timeMs: 0
}
};
到
template = {
node: "test",
transmit: {
timeMs: 0
}
};
我尝试过类似的事情,但我迷路了。
Utils.removeEmptyObjects = function(obj) {
return _.transform(obj, function(o, v, k) {
if (typeof v === 'object') {
o[k] = _.removeEmptyObjects(v);
} else if (!_.isEmpty(v)) {
o[k] = v;
}
});
};
_.mixin({
'removeEmptyObjects': Utils.removeEmptyObjects
});
您可以通过几个步骤来实现这一点:
使用 pickBy() 使用 isObject() 谓词来选取对象键值。
使用 mapValues() 递归调用
removeEmptyObjects()
,注意它只会用对象调用此函数。使用
omitBy()和 isEmpty() 谓词删除在
mapValues()
之后找到的所有空对象。使用 assign() 重新分配对象中的所有原始值,并使用
omitBy()
谓词进行 isObject()
。function removeEmptyObjects(obj) {
return _(obj)
.pickBy(_.isObject) // pick objects only
.mapValues(removeEmptyObjects) // call only for object values
.omitBy(_.isEmpty) // remove all empty objects
.assign(_.omitBy(obj, _.isObject)) // assign back primitive values
.value();
}
function removeEmptyObjects(obj) {
return _(obj)
.pickBy(_.isObject)
.mapValues(removeEmptyObjects)
.omitBy(_.isEmpty)
.assign(_.omitBy(obj, _.isObject))
.value();
}
_.mixin({
removeEmptyObjects: removeEmptyObjects
});
var template = {
node: "test",
representation: {
range: {}
},
transmit: {
timeMs: 0
}
};
var result = _.removeEmptyObjects(template);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
从没有嵌套对象的对象中删除未定义、null 和空字符串
_.omitBy(object, (v) => _.isUndefined(v) || _.isNull(v) || v === '');
对于嵌套对象,您可以使用递归函数来实现
它将删除任何级别的空对象、空数组、null、未定义、空字符串...
removeEmpty(obj) {
let finalObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] && typeof obj[key] === 'object') {
const nestedObj = removeEmpty(obj[key]);
if (Object.keys(nestedObj).length) {
finalObj[key] = nestedObj;
}
} else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
finalObj[key] = obj[key];
}
});
return finalObj;
}
更新2022年4月11日
根据@RahulSoni 评论,我刚刚修复了数组到对象的转换。现在一切都该处理了。如果您还有其他意见请告诉我
removeEmpty(obj) {
const finalObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
const nestedObj = this.removeEmpty(obj[key]);
if (Object.keys(nestedObj).length) {
finalObj[key] = nestedObj;
}
} else if (Array.isArray(obj[key])) {
if (obj[key].length) {
obj[key].forEach((x) => {
const nestedObj = this.removeEmpty(x);
if (Object.keys(nestedObj).length) {
finalObj[key] = finalObj[key] ? [...finalObj[key], nestedObj] : [nestedObj];
}
});
}
} else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
finalObj[key] = obj[key];
}
});
return finalObj;
}
示例:
const obj = {
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
array: [
{
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
obj: {
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
},
},
{
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
obj: {
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
},
},
],
b: {
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
c: {
a: '',
aa: null,
aaa: undefined,
aaaa: 'aaaa',
aaaaa: 0,
aaaaaa: 1,
aaaaaaa: 2,
aaaaaaaa: true,
aaaaaaaaa: false,
emptyObj: {},
emptyArray: [],
},
},
};
const finalObj = removeEmpty(obj);
console.log('finalObj After remove', finalObj);
这个(打字稿)也适用于数组并支持摇树:
import flow from "lodash/fp/flow";
import pickBy from "lodash/fp/pickBy";
import mapValues from "lodash/fp/mapValues";
import map from "lodash/fp/map";
import assign from "lodash/fp/assign";
import { default as fpOmitBy } from "lodash/fp/omitBy";
import { default as fpFilter } from "lodash/fp/filter";
import { isArray, isEmpty, isObject, omitBy } from "lodash-es";
export const compact = (obj) => !isObject(obj) ? obj : isArray(obj) ? compactArray(obj) : compactObject(obj);
const compactArray = (arr) => flow(
map(compact),
fpFilter(x => !isEmpty(x) || !isObject(x)),
)(arr)
const compactObject = (obj) => flow(
pickBy(isObject),
mapValues(compact),
fpOmitBy(isEmpty),
assign(omitBy(obj, isObject)),
)(obj);
这是 Amr 函数的修改版本,它解决了我遇到的问题,它提供如下输入:
const data = {
key1: 'value1',
topLevelKey1: {
key2: {}
},
key3: 'value3',
updates: [
{ toDeleteKey: {}, fullKey: 'has a value' },
{ toDeleteKey2: {}, fullKey2: 'has a value',
media: [
"https://thisisalink.com",
"https://thisisanotherlink.com",
]},
],
};
它将像对象一样对待媒体中的字符串并将它们分开:
"media":[{"0":"h","1":"t","2":"t","3":"p","4":"s"...
function removeEmpty(obj: Record<string, any>): Record<string, any> {
const finalObj: Record<string, any> = {};
Object.keys(obj).forEach((key) => {
if (obj[key] && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
const nestedObj = removeEmpty(obj[key]);
if (Object.keys(nestedObj).length) {
finalObj[key] = nestedObj;
}
} else if (Array.isArray(obj[key])) {
if (obj[key].length) {
finalObj[key] = obj[key].map((x) => {
if (typeof x === 'object' && !Array.isArray(x)) {
return removeEmpty(x);
} else {
return x;
}
});
}
} else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
finalObj[key] = obj[key];
}
});
return finalObj;
}
使用 fp 的更简单方法可能是:
const removeEmptyProperties = fp.omitBy(fp.isEmpty);
const compactObject = (obj: unknown) => {
return fp.mapValues((value: unknown) => {
if (fp.isObject(value)) {
return removeEmptyProperties(compactObject(value));
}
return value;
})(obj);
};
我正在为那些将来寻找此问题解决方案的人更新此内容。
lodash 提供了一种更简单的方法来做到这一点。
_.compact(arrayName) 将使用 lodash 从数组中删除所有空/未定义/空值
您可以使用
_.pick
仅选择您想要的属性,如
var desiredTemplate = _.pick(template, ['node','transmit']);
否则,据我所知,lodash 没有任何内置功能可以从对象中递归删除空对象/数组。