0

我正在开发一个 API,它将采用 2 个对象和一个表达式并执行过滤错误语句。返回第三个对象,该对象将仅具有表达式被评估为 true 的那些数据集。

var obj1 = [
        {cn: 101, name: "AA", seq:1},
        {cn: 106, name: "BB", seq:2}
    ];

var obj2 = [
        { cid: 100, name: "XX", locator: "r" },
        { cid: 101, name: "AA", locator: "p"},
        { cid: 507, name: "TT", locator: "r"}
    ];

var output = MyClass.filter(obj1, obj2, "{source.cn}==={target.cid}"); 

obj1 is source object
obj2 is target object

expected output is: 
output = [
         { cid: 101, name: "AA", locator: "p"}
     ];

因为我的类是一个通用类,它应该能够接受任何两个对象(任何结构和深度)并执行任何有效的 javascript 表达式。因此我找到给定表达式的路径并准备表达式列表。

source[0]["cn"]===target[0]["cid"]
source[0]["cn"]===target[1]["cid"]
source[0]["cn"]===target[2]["cid"]
source[1]["cn"]===target[0]["cid"]
source[1]["cn"]===target[1]["cid"]
source[1]["cn"]===target[2]["cid"]

得到表达式后,我评估每个表达式并过滤掉错误的表达式。

eval(source[0]["cn"]===target[0]["cid"]) >>>>>EVAL RESULT>>>>> false
eval(source[0]["cn"]===target[1]["cid"]) >>>>>EVAL RESULT>>>>> true 
eval(source[0]["cn"]===target[2]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[0]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[1]["cid"]) >>>>>EVAL RESULT>>>>> false 
eval(source[1]["cn"]===target[2]["cid"]) >>>>>EVAL RESULT>>>>> false 

当这 2 个对象包含 obj1 100 个可能的路径和 obj2 1000 个可能的路径时,myclass 生成 100,000 条语句来 eval。就是这样,它永远运行着众所周知的 eval 很慢,但由于这些语句是字符串,我无法将它放在“if”中

我尝试了一个测试代码,我在 if 语句中使用了语句,它非常 - 非常快。我想使用 if over eval。

我的测试代码如下:

var before = Date.now();
    var str, result, results = [], m, n;
    for(var i = 0, j=0; i <100000, j<100000; ++i,++j ){
        str = i + "===" + j;

        //eval(str)

        if(i === j) {
            result = true;
        } else {
            result = false;
        }           
    }

    var after = Date.now();
    console.log("Time: ", (after - before));

由于这些表达式可以是任何有效的 JS 表达式,我不能假设运算符。用户可以在表达式中自由使用任何类型的运算符(赋值、比较、算术、按位、逻辑、字符串或特殊运算符)。

例如 :

"{source.cn}==={target.cid} && {target.name} != 'XX'"
or
"({source.cn}==={target.cid} || {source.cn}/100 === 1 )&& {target.name} != 'XX'"
or anything else.

我不想编写自己的表达式解析器。

请提供帮助(不使用 eval) 1. 替代方法(但不是(new Function(expr)()) 2. 使用“if”而不是“eval”的某种方式将使我的代码非常快。就像上面的测试证明. 3. 任何其他在不影响要求的情况下使其快速的方法。(是的,目标对象中可能有多个匹配项)

提前致谢。

4

1 回答 1

3

首先可能不需要 eval 。

只需从传递字符串切换

var output = MyClass.filter(obj1, obj2, "{source.cn}==={target.cid}"); 

使用功能

function comparator(source, target) { 
    return source.cn===target.cid 
}

var output = MyClass.filter(obj1, obj2, comparator); 

你的过滤器会很简单!

function filter(array1,array2, comparator) {
  var ret = []
  array1.forEach(function(source) {
     array2.forEach(function(target) {
        if (comparator(source,target)) ret.push(source)
     }
  })

  return ret
}

当然,如果性能是一个问题,您将替换Array.forEach为 simple for

于 2013-10-03T20:05:05.597 回答