如何在JavaScript中高效求值带AND/OR的布尔条件列表?
高效化简并求解布尔条件列表
我有一个包含布尔条件的对象列表,每个对象的op字段表示当前条件与下一个条件的逻辑运算符,最后一个元素的op为null表示没有后续条件:
const conditions = [ {value: true, op: "AND"}, {value: true, op: "AND"}, {value: false, op: "OR"}, {value: true, op: null}, ]
需要高效化简并求解该条件,最终得到结果true。
一开始我尝试过迭代创建新列表的笨方法,接近目标但没成功,想找单循环或递归这类更高效的实现,却没做出来。
尝试1:reduce方法(无短路优化,存在失效场景)
我先写了一个reduce实现,但它没有利用布尔逻辑的短路特性提前退出,效率不足,而且后续发现存在失效场景:
const check = (results) => { return results.reduce((prev, cur) => { if (prev.op === "AND") { return {value: prev.value && cur.value, op: cur.op}; } return {value: prev.value || cur.value, op: cur.op}; }).value; }
尝试2:嵌套循环方法
之后改用嵌套循环,思路是把条件转成字符串拆分处理,逻辑更直观,但还是不够高效:
const checkWithLoops = (test) => { const andPairs = test.split("or"); const andResults = []; for (let i = 0; i < andPairs.length; i++) { const vals = andPairs[i].split(" "); let andRes = true; for (let o = 0; o < vals.length; o++) { if (vals[o] === "false") { andRes = false; } } andResults.push(andRes); } let orResult = false; for (let i = 0; i < andResults.length; i++) { if (andResults[i] === true) { orResult = true; break; } } return orResult; };
最优方案:利用布尔短路的单循环实现
要做到最高效,核心是利用布尔逻辑的短路特性减少冗余计算:
- 处理
AND链时,只要出现一个false,后续所有AND操作都不会改变结果,可直接跳过直到遇到OR - 处理
OR操作时,只要结果变为true,可直接返回,无需继续遍历
以下是符合条件列表结构的单循环实现,全程支持提前退出:
const evaluateConditions = (conditions) => { if (conditions.length === 0) return false; // 空列表默认返回false,可按需调整 let result = conditions[0].value; for (let i = 0; i < conditions.length - 1; i++) { const { op } = conditions[i]; const nextVal = conditions[i + 1].value; if (op === "AND") { result = result && nextVal; // AND短路:结果为false时,跳过后续所有连续的AND操作 if (!result) { while (i + 1 < conditions.length - 1 && conditions[i + 1].op === "AND") { i++; } } } else if (op === "OR") { result = result || nextVal; // OR短路:结果为true时直接返回,无需继续遍历 if (result) { return true; } } } return result; };
测试原条件的执行流程:
- 初始
result = true - 遍历到第1个元素(i=0),
op=AND,nextVal=true→result = true && true = true - 遍历到第2个元素(i=1),
op=AND,nextVal=false→result = true && false = false,此时跳过后续连续AND(这里下一个是OR,不跳过) - 遍历到第3个元素(i=2),
op=OR,nextVal=true→result = false || true = true,直接返回true,结束计算
这个实现只遍历到第3个元素就提前退出,没有冗余计算,是最高效的解法。
内容的提问来源于stack exchange,提问作者David Fariña
相关产品推荐
相关产品推荐

