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

在JavaScript中将动态字符串转换为逻辑表达式,javascript,object,ecmascript-6,Javascript,Object,Ecmascript 6,这可能有点困难,因为除了标准操作符之外,我还没有看到任何人尝试过 我有一个包含大约50k行对象的表,每行需要对它们运行一组表达式“最多30个”,并返回true或false。我已经用大量的十进制操作符成功地做到了这一点,但它很快就会变得一团糟 有人有更好的方法吗?下面的代码最少-问题在于验证函数 const objects = [ { 'First Name': 'Chris', 'Age': 18, 'Major': 'Mathemati

这可能有点困难,因为除了标准操作符之外,我还没有看到任何人尝试过

我有一个包含大约50k行对象的表,每行需要对它们运行一组表达式“最多30个”,并返回true或false。我已经用大量的十进制操作符成功地做到了这一点,但它很快就会变得一团糟

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


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'}  
]

常量对象=[
{
“名字”:“克里斯”,
年龄:18岁,,
"专业":"数学",,
“学院系”:“数学”
},
{
“First Name”:“null”,
年龄:21岁,,
"专业":"数学",,
“学院系”:“科学”
}
]
常量验证=(对象、规则)=>{
//将规则转换为逻辑表达式的逻辑
}
const results=objects.map(object=>{
变量标志=[]
flags.push(验证(对象,“[First Name]为null”))
flags.push(验证(对象'[Age]<[Required Age]'))
flags.push(验证(对象,“[Major]====[College Department]和[Age]>[Required Age]”)
//验证应该返回
//{规则:'[First Name]为null',标志:false/true,…原始对象和密钥对的其余部分}
//…返回标志数组
返回旗;
})
//结果应该是这样的
//假设要求的年龄是18岁
[
[
{规则:“[First Name]为空”,标志:false,“First Name”:“Chris”,“Age”:18,“Major”:“Mathematics”,“College Department”:“Mathematics”},
{规则:'[Age]<[Required Age]',标志:false,'名字':'Chris','Age':18,'专业':'Mathematics','College Department':'Mathematics'},
{规则:'[Major]====[学院系]和[Age]>[规定年龄]',标志:true,'名字':'Chris','Age':18,'专业':'数学','学院系':'数学'}
],
[
{规则:“[First Name]为空”,标志:true,'First Name':'null',年龄:21,'Major':'Mathematics','College Department':'Science'},
{规则:'[Age]<[Required Age]',标志:false,'First Name':'null','Age':21,'Major':'Mathematics','College Department':'Science'},
{规则:'[Major]====[College Department]和[Age]>[Required Age]',标志:false,'First Name':'null','Age':21,'Major':'Mathematics','College Department':'Science'}
]
]
//我知道如何将数组合并成一个,
//因此,上面的输出或下面的输出都有效
[
{规则:“[First Name]为空”,标志:false,“First Name”:“Chris”,“Age”:18,“Major”:“Mathematics”,“College Department”:“Mathematics”},
{规则:'[Age]<[Required Age]',标志:false,'名字':'Chris','Age':18,'专业':'Mathematics','College Department':'Mathematics'},
{规则:'[Major]====[学院系]和[Age]>[规定年龄]',标志:true,'First Name':'Chris','Age':18,'Major':'Mathematics','College Department':'Mathematics',
{规则:“[First Name]为空”,标志:true,'First Name':'null',年龄:21,'Major':'Mathematics','College Department':'Science'},
{规则:'[Age]<[Required Age]',标志:false,'First Name':'null','Age':21,'Major':'Mathematics','College Department':'Science'},
{规则:'[Major]====[College Department]和[Age]>[Required Age]',标志: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 } ]
*/

const object={Age:10,Required:18};
常量规则=[

{R:'[“Age”]<[“Required”]',O:['如果需要计算的表达式提前知道,请用代码写出表达式

const rules = new Map()
rules.set("[First Name] is null", function(object) {
    return object.firstName === null
})
创建自己的迷你语言需要大量的工作。如果您需要让用户添加自定义规则,那么构建规则解析器和评估引擎是有意义的


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

function parse(textInput) {
    return arrayOfTokens
}
示例文本输入:
[first Name]为空

令牌的示例数组:
[新字段(“名字”),新opisnll()]

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

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
    }
}

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

const rules = new Map()
rules.set("[First Name] is null", function(object) {
    return object.firstName === null
})
创建自己的迷你语言需要大量的工作。如果您需要让用户添加自定义规则,那么构建规则解析器和评估引擎是有意义的


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

function parse(textInput) {
    return arrayOfTokens
}
示例文本输入:
[first Name]为空

令牌的示例数组:
[新字段(“名字”),新opisnll()]

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

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
    }
}

经过几天的创建和修改,我开发了一种将字符串转换为逻辑表达式的解决方案。我在以下网站上制作了一个包:

安装

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
“严格使用”;
//必选模块
const ruleSet=require('validate-table-rules');
//将模块附加到对象原型
Object.prototype.rule=ruleSet.rules;
//声明并反对
常量对象=[
{年龄:18岁,必填项:21}
];
//示例案例->将名称传递给您
//要在附加的对象中检查
console.log(object.rule('[Age]<[Required]'))