Javascript - 递归查找数组中具有空值的键
Javascript - Recursively looking for keys in array with empty values
我创建了一个函数来递归查找嵌套数组中的空值。
函数 returns 一开始是正确的值,但似乎在返回结果之前将其重置为输入值。
我错过了什么?
这是我的代码:
const obj = [
{
mainContact: true,
contactName: "",
emailId: "abc@gmail.com",
contactAddress: [
{
addressType: "",
county: "U.K.",
postCode: "MK7 6BZ",
houseFlatNumber: 1
},
{
addressType: "def",
county: "France",
postCode: "123MKO",
houseFlatNumber: "223"
}
],
phoneDetails: [
{
notes: "",
phoneNumber: "1234567899",
countryCode: "44",
priority: "1"
},
{
notes: "Lorem ipsum",
phoneNumber: "1112223331",
countryCode: "48",
priority: "2"
}
]
}
];
function validObject(obj, isOk) {
for (var propName in obj) {
if (typeof obj[propName] === "object") {
this.validObject(obj[propName], isOk);
} else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
isOk = false;
break;
}
}
return isOk;
}
console.log(validObject(obj), true);
// This should return false but it returns true although it first hit the return isOk line
// with a false value then set it back to true
如有任何帮助,我们将不胜感激。
谢谢。
基本问题是您没有返回递归调用的值。所以你实际上在做的是执行一个内联递归循环,然后从父调用返回值。
另外,因为isOk
是一个原始布尔值,所以它是按值传递而不是按引用传递。因此在子函数调用中修改 isOk
不会修改父作用域中的变量。
注意:这不适用于 obj[propName]
(通过引用传递),因此对函数内部数据的任何修改都将保留在函数外部。
function validObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( validObject(obj[propName]) === false ) {
// This will propergate back through the call stack
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false; // we don't need a variable here
}
}
return true; // calculatus eliminatus, nothing is false, so it must be true
}
关于递归的事情是您必须 return 来自递归调用的值。这意味着您从内部调用该函数,然后相应地处理 return 值。
这是我对你的函数的解释,我在其中添加了一个简单的基本情况来检查传递的值是 null
、undefined
还是空字符串。
function isValidObject(obj) {
// Base case
if (obj[propName] === null || obj[propName] === undefined || obj[propName] === '') {
return false;
}
// Recurse through each item in object
if (typeof obj === "object") {
for (var propName in obj) {
if (!isValidObject(obj[propName]) {
return false;
}
}
}
return true;
}
请注意,这允许您摆脱传递到函数中的布尔参数,而当找到第一个时 return false .
感谢 James McGuigan,我编辑的版本如下:
isValidObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( this.isValidObject(obj[propName]) === false ||
obj[propName] === null ||
obj[propName].length === 0 )
{
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false;
}
}
return true;
}
另一种方法是编写一个更通用的函数来递归测试对象属性的有效性,给定要测试的谓词。
不难;在我看来,这通常比直接编写特定函数要简单。并将其应用到具体案例中也很简单。
它可能看起来像这样:
const isValid = (pred) => (obj) =>
Object .values (obj) .every (
v => (v && typeof v == 'object') ? isValid (pred) (v) : pred (v)
)
const noEmptyProps = isValid (v => v !== '' && v != null)
const obj = [{mainContact: true, contactName: "", emailId: "abc@gmail.com", contactAddress: [{addressType: "", county: "U.K.", postCode: "MK7 6BZ", houseFlatNumber: 1}, {addressType: "def", county: "France", postCode: "123MKO", houseFlatNumber: "223"}], phoneDetails: [{notes: "", phoneNumber: "1234567899", countryCode: "44", priority: "1"}, {notes: "Lorem ipsum", phoneNumber: "1112223331", countryCode: "48", priority: "2"}]}]
console.log (noEmptyProps (obj))
我创建了一个函数来递归查找嵌套数组中的空值。
函数 returns 一开始是正确的值,但似乎在返回结果之前将其重置为输入值。
我错过了什么?
这是我的代码:
const obj = [
{
mainContact: true,
contactName: "",
emailId: "abc@gmail.com",
contactAddress: [
{
addressType: "",
county: "U.K.",
postCode: "MK7 6BZ",
houseFlatNumber: 1
},
{
addressType: "def",
county: "France",
postCode: "123MKO",
houseFlatNumber: "223"
}
],
phoneDetails: [
{
notes: "",
phoneNumber: "1234567899",
countryCode: "44",
priority: "1"
},
{
notes: "Lorem ipsum",
phoneNumber: "1112223331",
countryCode: "48",
priority: "2"
}
]
}
];
function validObject(obj, isOk) {
for (var propName in obj) {
if (typeof obj[propName] === "object") {
this.validObject(obj[propName], isOk);
} else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
isOk = false;
break;
}
}
return isOk;
}
console.log(validObject(obj), true);
// This should return false but it returns true although it first hit the return isOk line
// with a false value then set it back to true
如有任何帮助,我们将不胜感激。
谢谢。
基本问题是您没有返回递归调用的值。所以你实际上在做的是执行一个内联递归循环,然后从父调用返回值。
另外,因为isOk
是一个原始布尔值,所以它是按值传递而不是按引用传递。因此在子函数调用中修改 isOk
不会修改父作用域中的变量。
注意:这不适用于 obj[propName]
(通过引用传递),因此对函数内部数据的任何修改都将保留在函数外部。
function validObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( validObject(obj[propName]) === false ) {
// This will propergate back through the call stack
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false; // we don't need a variable here
}
}
return true; // calculatus eliminatus, nothing is false, so it must be true
}
关于递归的事情是您必须 return 来自递归调用的值。这意味着您从内部调用该函数,然后相应地处理 return 值。
这是我对你的函数的解释,我在其中添加了一个简单的基本情况来检查传递的值是 null
、undefined
还是空字符串。
function isValidObject(obj) {
// Base case
if (obj[propName] === null || obj[propName] === undefined || obj[propName] === '') {
return false;
}
// Recurse through each item in object
if (typeof obj === "object") {
for (var propName in obj) {
if (!isValidObject(obj[propName]) {
return false;
}
}
}
return true;
}
请注意,这允许您摆脱传递到函数中的布尔参数,而当找到第一个时 return false .
感谢 James McGuigan,我编辑的版本如下:
isValidObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( this.isValidObject(obj[propName]) === false ||
obj[propName] === null ||
obj[propName].length === 0 )
{
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false;
}
}
return true;
}
另一种方法是编写一个更通用的函数来递归测试对象属性的有效性,给定要测试的谓词。
不难;在我看来,这通常比直接编写特定函数要简单。并将其应用到具体案例中也很简单。
它可能看起来像这样:
const isValid = (pred) => (obj) =>
Object .values (obj) .every (
v => (v && typeof v == 'object') ? isValid (pred) (v) : pred (v)
)
const noEmptyProps = isValid (v => v !== '' && v != null)
const obj = [{mainContact: true, contactName: "", emailId: "abc@gmail.com", contactAddress: [{addressType: "", county: "U.K.", postCode: "MK7 6BZ", houseFlatNumber: 1}, {addressType: "def", county: "France", postCode: "123MKO", houseFlatNumber: "223"}], phoneDetails: [{notes: "", phoneNumber: "1234567899", countryCode: "44", priority: "1"}, {notes: "Lorem ipsum", phoneNumber: "1112223331", countryCode: "48", priority: "2"}]}]
console.log (noEmptyProps (obj))