我正在开发一个API,它将获取2个对象和一个表达式并执行false语句的过滤。返回第三个对象,该对象只包含表达式求值为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
当这两个对象包含obj1 100个可能的路径和obj2 1000个可能的路径时,myclass会向eval生成100,000个语句。多数民众赞成它,它运行为众所周知的eval是缓慢但因为这些语句是字符串我不能把它放在“如果”
我尝试了一个测试代码,其中我在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.任何其他方法,使其快速而不影响要求。 (是的,目标对象可能有多个匹配)
提前致谢。
答案 0 :(得分:3)
首先可能不需要评估。
只需从传入字符串中切换
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
替换for
。