检查 n-depth POJO 中的所有属性都不为空
Check all properties are not null in n-depth POJO
我需要一个函数,如果每个 child 满足一个条件,它接受任何 object 和 returns true/false。目前该条件是 属性 为真。所以 null 和 undefined 应该 return false,但是 false 的值是 pass.
我正在做的项目是在 Typescript 中,但这也适用于 vanilla JS,我也可以使用 lodash。
到目前为止我已经开始使用这个功能:
function CheckAllPropertiesDefined(obj){
if (!obj) {
return false;
}
for (const key in obj) {
if (o[key] === null || o[key] === undefined) {
return false;
}
}
return true;
}
但是我正在做的事情的要求发生了变化(不再是平面 object),我意识到它不适用于嵌套属性。
运行 与此 object 的结果是正确的,但不应该是:
const obj = {
prop1: true,
prop2: true,
prop3: {
prop3a: false,
},
prop4: {
test: null,
foo: false,
child: {
child2: null,
},
},
};
它应该 return 为假,因为 prop4.test
和 prop4.child.child2
为空。我认为一些递归是必要的。
所以 30 秒后 post 我拿出了一个绘图工具 (iPad) 并写下了解决这个问题的逻辑步骤并找到了解决方案。我强烈建议在卡住而不是 运行 互联网时这样做。
我无法在 SO 上找到适合此特定问题的解决方案,所有解决方案都仅适用于非嵌套 POJO。
如果有人可以改进它,我愿意接受。
这是我在 Javscript 中的解决方案:
function CheckAllPropertiesDefined(obj) {
if (!obj) {
return false;
}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object") {
if (!CheckAllPropertiesDefined(obj[key])) {
return false;
}
}
if (obj[key] === null || obj[key] === undefined) {
return false;
}
}
}
return true;
}
我通常更喜欢将对象的遍历与我们对其执行的操作分开。在这里,我将编写一个通用函数,它可以对任何(标量)节点应用谓词,并对对象或数组进行递归。然后我们可以简单地用一个测试节点不是 null
或 undefined
的函数来调用它,以取回用于测试对象的函数。这是一个例子:
const checkAllDeep = (pred) => (xs) =>
Array .isArray (xs)
? xs .every (x => checkAllDeep (pred) (x))
: xs && typeof xs == 'object'
? Object .entries (xs) .every (([k, v]) => checkAllDeep (pred) (v))
: pred (xs)
const checkAllPropertiesDefined = checkAllDeep (x => x !== null && x !== undefined)
const obj = {prop1: true, prop2: true, prop3: {prop3a: false}, prop4: {test: null, foo: false, child: {child2: null}}}
console .log (checkAllPropertiesDefined (obj))
以后如果我们想改变谓词(例如我们想接受null
而不是undefined
),很容易找到。我们可以很简单地编写其他函数,例如 const allPropsAreStrings (checkAllDeep ((x) => typeof x == 'string')
。
我需要一个函数,如果每个 child 满足一个条件,它接受任何 object 和 returns true/false。目前该条件是 属性 为真。所以 null 和 undefined 应该 return false,但是 false 的值是 pass.
我正在做的项目是在 Typescript 中,但这也适用于 vanilla JS,我也可以使用 lodash。
到目前为止我已经开始使用这个功能:
function CheckAllPropertiesDefined(obj){
if (!obj) {
return false;
}
for (const key in obj) {
if (o[key] === null || o[key] === undefined) {
return false;
}
}
return true;
}
但是我正在做的事情的要求发生了变化(不再是平面 object),我意识到它不适用于嵌套属性。
运行 与此 object 的结果是正确的,但不应该是:
const obj = {
prop1: true,
prop2: true,
prop3: {
prop3a: false,
},
prop4: {
test: null,
foo: false,
child: {
child2: null,
},
},
};
它应该 return 为假,因为 prop4.test
和 prop4.child.child2
为空。我认为一些递归是必要的。
所以 30 秒后 post 我拿出了一个绘图工具 (iPad) 并写下了解决这个问题的逻辑步骤并找到了解决方案。我强烈建议在卡住而不是 运行 互联网时这样做。
我无法在 SO 上找到适合此特定问题的解决方案,所有解决方案都仅适用于非嵌套 POJO。
如果有人可以改进它,我愿意接受。
这是我在 Javscript 中的解决方案:
function CheckAllPropertiesDefined(obj) {
if (!obj) {
return false;
}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object") {
if (!CheckAllPropertiesDefined(obj[key])) {
return false;
}
}
if (obj[key] === null || obj[key] === undefined) {
return false;
}
}
}
return true;
}
我通常更喜欢将对象的遍历与我们对其执行的操作分开。在这里,我将编写一个通用函数,它可以对任何(标量)节点应用谓词,并对对象或数组进行递归。然后我们可以简单地用一个测试节点不是 null
或 undefined
的函数来调用它,以取回用于测试对象的函数。这是一个例子:
const checkAllDeep = (pred) => (xs) =>
Array .isArray (xs)
? xs .every (x => checkAllDeep (pred) (x))
: xs && typeof xs == 'object'
? Object .entries (xs) .every (([k, v]) => checkAllDeep (pred) (v))
: pred (xs)
const checkAllPropertiesDefined = checkAllDeep (x => x !== null && x !== undefined)
const obj = {prop1: true, prop2: true, prop3: {prop3a: false}, prop4: {test: null, foo: false, child: {child2: null}}}
console .log (checkAllPropertiesDefined (obj))
以后如果我们想改变谓词(例如我们想接受null
而不是undefined
),很容易找到。我们可以很简单地编写其他函数,例如 const allPropsAreStrings (checkAllDeep ((x) => typeof x == 'string')
。