我正在寻找在循环中制作动态生成条件的最佳方法。
一个价值千字的样本,所以这是我的代码:
var condition = "data.label == 'Test'";
for (var key in andArray) {
condition += "&& " + andArray[key];
}
for (var key in orArray) {
condition += "|| " + orArray[key];
}
var length = dataArray.length;
var result = [];
for (var i = 0; i < length; i++) {
var data = dataArray[i];
if (eval(condition)) {
result.push(obj);
}
}
我使用eval()
功能,效果很好,但实在太慢了!对于200个元素的数组,此代码需要25ms才能执行!
这是不可接受的,因为我知道我将在具有数千个元素的数组上使用这种东西。
您是否有想法以更快的方式做到这一点?
答案 0 :(得分:2)
创建一个new Function()
,这样字符串只会被解析一次:
var length = dataArray.length;
var result = [];
var fn = new Function('data', 'return ' + whereCondition);
for (var i = 0; i < length; i++) {
var data = dataArray[i];
if (fn(data)) {
result.push(obj);
}
}
答案 1 :(得分:2)
我想建议一个没有字符串操作的替代解决方案。相反,你可以组合功能。通过函数组合而不是字符串操作来构建代码应该不易出错 - 并且肯定不那么“hacky”(无论这意味着什么......)。
Javascript具有一阶函数,您可以传递(并组合)谓词。谓词是一个返回布尔值的函数。例如:
var isLabelTest = function(obj) {
return obj.label === 'test';
}
您可以将它们存储为谓词函数,而不是将条件存储为字符串 然后你可以编写一些函数来获取谓词并返回新的谓词:
var binaryAnd = function(predA, predB) {
return function(obj) {
return predA(obj) && predB(obj);
};
};
var binaryOr = function(predA, predB) {
return function(obj) {
return predA(obj) || predB(obj);
};
};
您还可以编写带有谓词数组的函数,并将数组中的所有谓词组合成一个新的谓词:
var and = function(preds) {
return preds.reduce(binaryAnd, function(obj) {return true;});
};
var or = function(preds) {
return preds.reduce(binaryOr, function(obj) {return false;});
};
现在给出一个谓词的“andArray”,它们都需要返回true
,并且谓词的“orArray”至少有一个需要返回true
,下面的代码完成了这项工作:
var results = [];
var combinedPredicate = binaryAnd(and(andArray), or(orArray));
var pushIfCondition = function (obj) {
results.push(combinedPredicate(obj));
};
dataArray.forEach(pushIfCondition);
最后,请注意,没有必要自己编写用于组合谓词的函数,像ramda这样的库可以提供更有效的实现。
答案 2 :(得分:0)
这是一个简单的例子:
const conditions = [false, 0, 'blah', 1]; // whatever conditions you like
conditions.reduce((previousCond, actualCond) =>
previousCond || actualCond, false)); // => 'blah'
我喜欢这一点,因为它表现为真实条件并返回真实值,而不仅仅是布尔值。
如果要返回布尔值,则可以使用:
conditions.some(cond => cond); // => true
如果要使用和条件用户Array.every
而不是.some
答案 3 :(得分:0)
这是使用filter
示例1:
> const num = 10
> const rules = []
> rules.push(num > 5) // true
> rules.push(num % 2 !== 0) // to check if it is odd number w/c will be "false"
> console.log(rules)
< [true, false]
> rules.filter((rule) => rule === true).length === rules.length
< false // Did not pass all the conditions
示例2
> const num = 7
> const rules = []
> rules.push(num > 5) // true
> rules.push(num % 2 !== 0) // true
> console.log(rules)
< [true, true]
> rules.filter((rule) => rule === true).length === rules.length
< true // Passed all the conditions