简介
多条件同时判断,并且每个条件都可以影响结果的情况下,如果 if-else 直接判断的话,特别容易混乱,判读出错。
我们可以根据二进制数据的特性,每一位都看做是一个 bool 值。
假如要在四个条件的组合中判断是否为真,可将每一个条件作为二进制中的一位,按从右到左的顺序编号。
四个条件分别为 a,b,c,d ,从右到左分别对应最后 4 位,然后将对应的值保存变量中,如:
a=true,b=false,c=true,d=true,得到的二进制为:result=1011
需要判断 a,c,d,都为真时,在组合条件校验中可简化为:
if(result & 11 == 11) //todo
//or 转为10进制
if(parseInt("result",2) == 11) //todo
在有 n 个组合条件的情况,依此类推。
代码实现
位移运算实现
function conditionValue1(datas: (string | boolean | number)[]): number {
let n = 0;
let strs: string[] = [];
datas.reverse().forEach((value, index) => {
const yes = value && value == "1";
strs.push(yes ? "1" : "0");
n += Math.pow(2, index) >> (yes ? 0 : index + 1);
});
console.log(strs);
return n;
}
//测试
console.log(conditionValue1(["1", "0", 1, 0, true, false]));
//结果
101010;
42;
字符串拼接实现
function conditionValue2(datas: (string | boolean | number)[]): number {
let n = "";
datas.forEach((value, index) => {
const yes = value && value == "1";
n += yes ? "1" : "0";
});
console.log(n);
return parseInt(n, 2);
}
//测试
console.log(conditionValue2(["1", "0", 1, 0, true, false]));
//结果
101010;
42;
实例
假设我们有如下判断表:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|
提前打碎 | N | N | N | N | Y | Y | Y | Y |
上个周期奖励>0 | N | Y | N | Y | N | Y | N | Y |
本次周期奖励>0 | N | N | Y | Y | N | N | Y | Y |
结果 | 领取(灰) | 领取(亮) | 领取(灰) | 领取(亮) | 打碎(灰) | 领取(亮) | 打碎(亮) | 领取(亮) |
动作 | 无 | 领取奖励 | 无 | 领取奖励 | 无 | 领取奖励 | 打碎奖励 | 领取奖励 |
从表中可以得知:
- 条件 a=是否提前打碎
- 条件 b=上个周期奖励>0
- 条件 c=本次周期奖励>0
在有清晰的判断的表的情况下,我们很容易得出如下代码。
private initBtnType() {
if (this._confData) {
const a = this._confData.early_break_status;
const b = this._confData.previous_rebate_amount > 0;
const c = this._confData.current_rebate_amount > 0;
const result = this.conditionValue([a, b, c]);
switch (result + 1) {
case 2:
case 4:
case 6:
case 8:
//领取(亮)
break;
case 7:
//打碎(亮)
break;
case 5:
//打碎(灰)
break;
default:
//领取(灰)
break;
}
}
}
总结
- 这种代码方式可读性不好,对后续接手工作的人不友好。
- 所以设计前需要有逻辑清晰的判断表。
- 判断条件越多这种代码越方便,两个条件的则不需要。