【问题标题】:How to check if all numbers in an object are within a certain range?如何检查对象中的所有数字是否在一定范围内?
【发布时间】:2015-03-09 01:34:53
【问题描述】:

我想在我当前的 JS/jQuery 项目中包含的功能之一是允许用户导出和导入他们保存的数据。导入/导出数据只是通过 JSON.stringify 和 JSON.parse 运行的一个大对象,并且实现它的基本版本运行良好,但我想验证导入的数据以确保它能够正常工作(这个不是关于作为 JavaScript 工作,而是更多关于在我正在制作的游戏规则内工作)。

我想提出一个更有效的脚本来验证这个大而复杂的对象。我关心的对象的唯一部分是数字,但它还包括字符串、数组、嵌套对象。一些嵌套对象包括我关心的数字,但还有更多其他垃圾,包括更进一步的嵌套对象。目前,我正在使用 jQuery 的 each() 函数来遍历对象的每个子部分并对其进行评估,但这需要我为我关心的每个子部分编写一个 each 函数。

如何为整个对象提供函数并让它只查看数字以查看它们是大于还是小于设定值?

编辑:在此处粘贴对象,目的是检查是否所有数字。有些需要在 0 到 3 之间,有些需要在 0 到 9 之间。

{
"meta": {
    "id": 2,
    "name": "Test",
    "concept": "test description"
},
"coreAttributes": {
    "Strength": 3,
    "Finesse": 1,
    "Perception": 9,
    "Stamina": 1,
    "Agility": 1,
    "Wits": 1,
    "Willpower": 1,
    "Charisma": 1,
    "Intelligence": 1
},
"skills": {
    "Toughness": ["Strength", "STR", 0],
    "Stealth": ["Finesse", "FIN", 0],
    "Alertness": ["Perception", "PER", 3],
    "Investigate": ["Perception", "PER", 0],
    "Athletics": ["Agility", "AGI", 0],
    "Drive": ["Wits", "WIT", 0],
    "Survival": ["Wits", "WIT", 0],
    "Guts": ["Willpower", "WIL", 4],
    "Hardware": ["Intelligence", "INT", 0],
    "Humanities": ["Intelligence", "INT", 0],
    "Medicine": ["Intelligence", "INT", 0],
    "Science": ["Intelligence", "INT", 0],
    "Software": ["Intelligence", "INT", 0],
    "Charm": ["Charisma", "CHA", 0],
    "Manipulate": ["Charisma", "CHA", 0]
},
"unrolledSkills": {
    "Contacts": 0,
    "Languages": 0,
    "Resources": 0
},
"combatSkills": {
    "Unarmed": ["Strength", "STR", 0],
    "Defense": ["Finesse", "FIN", 0],
    "Melee": ["Finesse", "FIN", 0],
    "Firearms": ["Perception", "PER", 0],
    "Ballistics": ["Perception", "PER", 0],
    "Initiative": ["Wits", "WIT", 0]
},
"attacks": {},
"status": {
    "currentEndurance": 4,
    "currentSpeed": 4,
    "currentEntanglement": 4,
    "body": {
        "upper": {
            "wounds": 0,
            "armor": ["", 0]
        },
        "lower": {
            "wounds": 0,
            "armor": ["", 0]
        },
        "main": {
            "wounds": 0,
            "armor": ["", 0]
        },
        "off": {
            "wounds": 0,
            "armor": ["", 0]
        },
        "legs": {
            "wounds": 0,
            "armor": ["", 0]
        }
    }
},
"styles": {
    "classes": {
        "Strength": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Finesse": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Perception": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Stamina": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Agility": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Wits": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Willpower": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Charisma": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        },
        "Intelligence": {
            "core": 0,
            "spec1": 0,
            "spec2": 0,
            "spec3": 0,
            "aux1": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux2": {
                "skill": false,
                "name": "",
                "value": 0
            },
            "aux3": {
                "skill": false,
                "name": "",
                "value": 0
            }
        }
    },
    "arcane": {
        "restoration": 0,
        "evocation": 0,
        "abjuration": 0,
        "sublimation": 0,
        "paradigm": 0,
        "telepathy": 0,
        "shift": 0,
        "electromagnetism": 0,
        "gravitonertia": 0,
        "chromodynamism": 0,
        "technology": 0
    },
    "extension": {
        "avatar": 0,
        "proxy": 0,
        "permanence": 0
    }
},
"addenda": {}

}

【问题讨论】:

  • 你要找的词是递归。
  • 我们要找的词是示例代码。
  • @Kris 你必须告诉我们哪些数字可以属于哪个范围。
  • 该死,我很想回答这个问题,但是没有足够的规范来这样做。
  • 程序如何知道范围是 0-3 和 0-9?运行多个测试不是更好吗?

标签: javascript validation range


【解决方案1】:

下面使用递归在多维对象中的所有键中搜索任何小于或大于提供的数字的数字。

只需调用checkObject(myStuff, 30, 60); 之类的函数,传入您的对象、允许的最小数字和允许的最大数字

var myStuff = { "results": [
	{
        "ACL": {
            "7UeILO5tC4": {
                "count": "45",
                "read": true
            },
            "role:Leads": {
                "count": "12",
                "read": true,
                "write": true
            }
        },
        "createdAt": "2014-12-16T22:04:46.338Z",
        "finishDate": "12%2F16%2F2014",
        "finishTime": "16%3A4%3A44",
        "objectId": "tVldoxxdCB",
        "passFail": "Pass",
        "passingPercentage": "56",
        "passingPoints": "34",
        "questions": "21",
        "quizName": "Name",
        "quizType": "Flights",
        "teamMember": "Jame Fellows",
        "ttlPossiblePoints": "59",
        "updatedAt": "2014-12-16T22:04:46.338Z",
        "userName": "Jame.Fellows",
        "userPercentage": "95",
        "userPoints": "20",
        "userRightAnswers": "57"
    },

	{
        "ACL": {
            "7UeILO5tC4": {
                "count": "44",
                "read": true
            },
            "role:Leads": {
                "count": "12",
                "read": true,
                "write": true
            }
        },
        "createdAt": "2014-12-16T22:04:46.338Z",
        "finishDate": "12%2F16%2F2014",
        "finishTime": "16%3A4%3A44",
        "objectId": "tVldoxxdCB",
        "passFail": "Pass",
        "passingPercentage": "90",
        "passingPoints": "87",
        "questions": "21",
        "quizName": "Name",
        "quizType": "Flights",
        "teamMember": "Jame Fellows",
        "ttlPossiblePoints": "79",
        "updatedAt": "2014-12-16T22:04:46.338Z",
        "userName": "Jame.Fellows",
        "userPercentage": "76",
        "userPoints": "20",
        "userRightAnswers": "45"
    },
	{
        "ACL": {
            "7UeILO5tC4": {
                "count": "45",
                "read": true
            },
            "role:Leads": {
                "count": "12",
                "read": true,
                "write": true
            }
        },
        "createdAt": "2014-12-16T22:04:46.338Z",
        "finishDate": "12%2F16%2F2014",
        "finishTime": "16%3A4%3A44",
        "objectId": "tVldoxxdCB",
        "passFail": "Pass",
        "passingPercentage": "90",
        "passingPoints": "19",
        "questions": "21",
        "quizName": "Name",
        "quizType": "Flights",
        "teamMember": "Jame Fellows",
        "ttlPossiblePoints": "21",
        "updatedAt": "2014-12-16T22:04:46.338Z",
        "userName": "Jame.Fellows",
        "userPercentage": "95",
        "userPoints": "20",
        "userRightAnswers": "20"
    }
] };

  
// track how many invalid numbers we find
var hasInvalidData=0;


// call our checkObject() function, pass it
// your object, your lowest allowed number, your highest allowed number
checkObject(myStuff, 30, 60);

if(hasInvalidData > 0){
  alert(hasInvalidData + ' invalid numbers were found')
}

function checkObject(object, low, high){
  
    // loop through each property of the object
    for (var property in object) {
      
        // make sure it's a real property and not inherited
        if (object.hasOwnProperty(property)) {
             
             //get the value of the current property
             var value = object[property];
             
             // if this propery is itself an object, 
             // call this function recursively  
             if(typeof object[property] == "object" && typeof object[property] !== null){
               checkObject(object[property], low, high)
             }
             else{
                // if it's not an object 
                // check if it a a number and not true or false 
                // which wihich isNaN sees as 1 and 0
                if( !isNaN(value) && typeof value != "boolean"){
                   console.log(value);
                   if(value < low){
                     console.log('^ this value is too small ^');
                     hasInvalidData++;
                   }
                   if(value > high){
                     console.log('^ this value is too large ^');
                     hasInvalidData++;
                   }
                }
             }
        }
    }
}

【讨论】:

  • 我喜欢这个解决方案,我可能会在这些方面使用一些东西。这应该允许我测试我需要测试的几个不同的范围。
【解决方案2】:

你要找的其实很简单——递归。
下面的代码检查是否所有数字都大于或等于 2,并在第一个不匹配的数字上返回 false。

var x = {
    b: 5,
    c: {
        d: 3,
        e: [1, 2, 3],
        f: function() {}
    },
    g: function() {}
};

var recurse = function(a) {
    var s = true;
    for (prop in a) {
        switch (typeof a[prop]) {
            case "number":
                //Check for conditions here
                console.log("found number " + a[prop]);
                if (a[prop] < 2) {
                    return false;
                }
                break;
            case "object":
                if (a[prop] !== null) {
                    s = s && recurse(a[prop]);
                }
                break;
            default:
                break;
        }
    }
    return s;
}

recurse(x);

【讨论】:

  • 您的代码无法正确处理 null 值,因为 null 的 typeof 是对象。
  • @plalx 感谢您的评论,添加了一个条件。
【解决方案3】:

这是一个迭代解决方案:

var x = {
    b: 5,
    c: {
        d: 3,
        e: [1, 2, 3],
        f: function() {}
    },
    g: function() {}
};

function check (obj) {
    var queue = [obj];
    while (queue.length > 0) {
        var current = queue.shift();
        for (var prop in current) {
            if (!current.hasOwnProperty(prop)) continue;
            switch (typeof(current[prop])) {
                case "number":
                    // check for conditions here
                    if (current[prop] < 2) {
                        return false;
                    }
                    break;
                case "object":
                    if (current[prop] !== null) {
                        queue.push(current[prop]);
                    }
                    break;
                default:
                    break;
            }
        }
    }
    return true;
}

alert(check(x));

因为可以提早完成,所以速度有点快

【讨论】:

    【解决方案4】:

    给你,你只需要这个:(它也有一些花哨的可视化:P)

    function traverse(obj, callback, level) {
        for (var i in obj) {
            if (!obj.hasOwnProperty(i)) continue;
            callback.apply(this, [i, obj[i], level||""]);  
            (obj[i] !== null && typeof(obj[i])=="object") && traverse(obj[i],callback,(level||"")+" ");
        }
    }
    
    // it is called like this
    traverse(obj, valueCheck); 
    
    //obj  -  is your object as in your question
    //valueCheck(key, val, level)  -  is your own function to check the value
    

    valueCheck() 的一个示例函数可能如下所示

    function valueCheck(key, val, level) {
        // proceed to check only if the value is a number
        if (!isNaN(parseFloat(val)) && isFinite(val)) { 
            var isError = ! ((0 <= val) && (val <= 9));
            console.log(level + key + " : " + val + (isError && " ----------------------- VALUE ERROR" || ""));
        } else {
            // if it's a new object, print shiny "-" at the begining
            (typeof val == "object") && console.log(Array(1+level.length).join("-") + key);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-30
      • 2021-03-15
      • 2014-05-05
      • 1970-01-01
      • 2015-11-28
      • 2018-11-04
      • 2018-06-07
      • 2020-03-19
      相关资源
      最近更新 更多