代码之家  ›  专栏  ›  技术社区  ›  xchrisbradley

在JavaScript中将动态字符串转换为逻辑表达式

  •  0
  • xchrisbradley  · 技术社区  · 7 年前

    有人有更好的方法吗?下面的代码最少-问题在于验证函数。

    
    const objects = [
        {
            'First Name': 'Chris',
            'Age': 18,
            'Major': 'Mathematics',
            'College Department': 'Mathematics'
        },
        {
            'First Name': 'null',
            'Age': 21,
            'Major': 'Mathematics',
            'College Department': 'Science'
        }
    ]
    
    const validate = (object, rule) => {
        // logic to convert rule to logical expression
    }
    
    const results = objects.map(object => {
        var flags = []
        flags.push(validate(object, '[Fist Name] is null'))
        flags.push(validate(object, '[Age] < [Required Age]'))
        flags.push(validate(object, '[Major] === [College Department] and [Age] > [Required Age]'))  
        // Validate is supposed to return 
        // {Rule: '[Fist Name] is null', Flag: false/true, ...Rest of original object and key pairs} 
    
        // ... Return array of flags
        return flags;
    })
    
    // Result should look like this
    // lets say required age is 18
    [
        [
            {Rule: '[Fist Name] is null', Flag: false, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'},
            {Rule: '[Age] < [Required Age]', Flag: false, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'},
            {Rule: '[Major] === [College Department] and [Age] > [Required Age]', Flag: true, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'}   
        ],
        [
            {Rule: '[Fist Name] is null', Flag: true, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'},
            {Rule: '[Age] < [Required Age]', Flag: false, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'},
            {Rule: '[Major] === [College Department] and [Age] > [Required Age]', Flag: false, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'}  
        ]
    ]
    
    // I know how to concat the arrays into one, 
    // so either the above output works or the one below works
    [
        {Rule: '[Fist Name] is null', Flag: false, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'},
        {Rule: '[Age] < [Required Age]', Flag: false, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'},
        {Rule: '[Major] === [College Department] and [Age] > [Required Age]', Flag: true, 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathematics', 'College Department': 'Mathematics'}, 
        {Rule: '[Fist Name] is null', Flag: true, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'},
        {Rule: '[Age] < [Required Age]', Flag: false, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'},
        {Rule: '[Major] === [College Department] and [Age] > [Required Age]', Flag: false, 'First Name': 'null', 'Age': 21, 'Major': 'Mathematics', 'College Department': 'Science'}  
    ]
    

    使现代化 这就是我已经走了多远,但我只能为>,做这件事<=&燃气轮机;至少到目前为止我只测试了这些。我很快会添加更多详细的评论。

    
    const object = {Age: 10, Required: 18};
    const rules = [
        {R: '["Age"] < ["Required"]', O: ['<']},
        {R: '["Age"] <= ["Required"]', O: ['<=']},
        {R: '["Age"] > ["Required"]', O: ['>']},
    ]
    
    // Prototype that will parse the string
    // ... then return the indexes of char
    // ... we will use this to insert object name before the char
    String.prototype.toIndices = function (d) { return this.split("").reduce((a, e, i) => e === d ? a.concat(i) : a, []) };
    
    String.prototype.splice = function(idx, rem, str) {
        return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
    };
    
    Object.prototype.validateRule = function (r) {
        const newString = r['R'].toIndices("[").map(s => {
            return r['R'].splice(s, 0, 'object');
        })
    
        var exp = [];
    
        for (let item = 0; item < newString.length; item++) {
            for (let obj = 0; obj < newString[item].split(" ").length; obj++) {
                if (newString[item].split(" ")[obj].includes("object"))
                    exp.push(newString[item].split(" ")[obj])
            }
        }
    
        return [...exp].map((e, i) => i < exp.length - 1 ? [e, r['O'][0]] : [e]).reduce((a, b) => a.concat(b)).join(" ");
    }
    
    
    console.log({Rule: rules[0]['R'], Flag: eval(object.validateRule(rules[0]))});
    // output
    /*
    { Rule: '["Age"] < ["Required"]', Flag: true }
    */
    
    console.log(rules.map(rule => { return {Rule: rule['R'], Flag: eval(object.validateRule(rule))} }));
    // output
    /*
    [ { Rule: '["Age"] < ["Required"]', Flag: true },
      { Rule: '["Age"] <= ["Required"]', Flag: true },
      { Rule: '["Age"] > ["Required"]', Flag: false } ]
    */
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   AJcodez    7 年前

    如果需要计算的表达式提前知道,请用代码写出表达式。

    const rules = new Map()
    rules.set("[First Name] is null", function(object) {
        return object.firstName === null
    })
    

    创建自己的迷你语言需要大量的工作。如果您需要让用户添加自定义规则,那么构建规则解析器和评估引擎是有意义的。


    在解析代码时,计算表达式的方法通常是将输入分解为标记,然后在第二步中计算标记。

    function parse(textInput) {
        return arrayOfTokens
    }
    

    [Fist Name] is null

    令牌的示例数组: [ new Field("First Name"), new OpIsNull() ]

    为不同的文本输入编写大量的单元测试,并确保它返回预期的标记。当解析工作正常时,下一步是评估令牌。为令牌、对象和预期输出值的数组编写大量单元测试。

    function evaluate(object, tokens) {
        let leftHand = null
        if (tokens[0] instanceof Field) {
            leftHand = getFieldValue(object, tokens[0])
        }
        if (tokens[1] instanceof OpIsNull) {
            return leftHand === null
        }
        // etc
    }
    
    function getFieldValue(object, field) {
        if (field.name == "First Name") {
            return object.firstName
        }
    }
    
        2
  •  0
  •   xchrisbradley    7 年前

    https://www.npmjs.com/package/validate-table-rules

    安装

    npm install validate-table-rules
    

    快速启动

    'use strict';
    
    //  Required module
    const ruleSet = require('validate-table-rules');
    
    // Attach module to Object prototype
    Object.prototype.rule = ruleSet.rules;
    
    // Declare and object
    const object = [
        {Age: 18, Required: 21}
    ];
    
    // Sample case -> pass in names you
    // want to check for in attached object
    console.log(object.rule('[Age] < [Required]')) // output = true
    console.log(object.rule('[Age] > [Required]')) // output = false
    

    享受