这样的的代码过于臃肿,不容易理解,后期维护难度大
const isDel = (op, o) => {
let fal = false;
if (op.is_show_lock && op.is_show_sf && op.is_show_bz) {
if (o.is_lock && o.is_sf && o.is_bz) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_lock && op.is_show_sf) {
if (o.is_lock && o.is_sf) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_lock && op.is_show_bz) {
if (o.is_lock && o.is_bz) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_sf && op.is_show_bz) {
if (o.is_sf && o.is_bz) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_lock) {
if (o.is_lock) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_sf) {
if (o.is_sf) {
fal = false;
} else {
fal = true;
}
} else if (op.is_show_bz) {
if (o.is_bz) {
fal = false;
} else {
fal = true;
}
}
return fal;
};
优化思路
观察问题,总结规律:
op.is_show_xxx 和 o.is_xxx 成对出现
当 op.is_show_xxx 为 true 的时候才需要判断 o.is_xxx (过滤)
将过滤出来的所有 o.is_xxx 用 &&组合条件,得到计算结果
最终结果正好与计算结果相反
因为 op.is_show_xxx 和 op.is_xxx 数量相当,而且不多。原回答(见下面)通过数组索引的方式来关联他们。然后在一次遍历(reduce 部分)中同时进行过滤(三元运算)和布尔计算(合并 r 值)。因为是 and 运算,所以初始值给 true 。最后将结果取反输出。
原回答这个解法虽然有一定的效率,但不是很容易理解,今天再写个按上面分析分步骤进行的:
function isRemove2(op, o) {
const result = "lock,sf,bz".split(",")
.map(suffix => [`is_show_${suffix}`, `is_${suffix}`])
.map(pair => ({ flag: op[pair[0]], value: o[pair[1]] }))
// ⇑ 上面三行都只是为了生成 { flag: true, value: true } 这样的关系数据
// ⇓ 下面这行是按 is_show_xxx 过滤
.filter(pair => pair.flag)
// 过滤出来的用 && 组合逻辑
.reduce((r, pair) => r && pair.value, true);
return !result;
}
不习惯看这种函数式的处理方式,来个原始一点for…of 循环的
function isRemove3(op, o) {
const suffixes = "lock,sf,bz".split(",");
let result = true;
for (const suffix of suffixes) {
if (op[`is_show_${suffix}`]) {
result &&= o[`is_${suffix}`];
}
}
return !result;
}
这一段中的遍历部分(初始化 result 和 for )直接翻译成 reduce 形式就是:
function isRemove4(op, o) {
const suffixes = "lock,sf,bz".split(",");
let result = suffixes.reduce(
(r, suffix) => {
if (op[`is_show_${suffix}`]) {
return r && o[`is_${suffix}`];
} else {
return r;
}
},
true // 初始化,相当于 let result = true
);
return !result;
}
中间的 if…else…看起来不清爽,处理一下(VS 的重构很方便)
function isRemove4(op, o) {
const suffixes = "lock,sf,bz".split(",");
let result = suffixes.reduce(
(r, suffix) => op[`is_show_${suffix}`] ? r && o[`is_${suffix}`] : r,
true // 初始化,相当于 let result = true
);
return !result;
}
问题中的 isDel 保留,方便做单元测试对比,定义了一个 isRemove:
function isRemove(op, o) {
const flags = [op.is_show_lock, op.is_show_sf, op.is_show_bz];
const values = [o.is_lock, o.is_sf, o.is_bz];
return !flags.reduce((r, flag, i) => {
return flag ? r && values[i] : r;
}, true);
}
测试用例:
// test cases
(() => {
const cases = Array.from(Array(8), (_, i) => {
return [!!(i & 0x01), !!(i & 0x02), !!(i & 0x04)];
});
let failed = false;
const allCases = cases.length * cases.length;
let passed = 0;
cases.forEach(flags => {
const op = {};
([op.is_show_lock, op.is_show_sf, op.is_show_bz] = flags);
cases.forEach(values => {
const o = {};
([o.is_lock, o.is_sf, o.is_bz] = values);
if (isDel(op, o) === isRemove(op, o)) {
passed++;
} else {
failed = true;
console.log("[Fail]", op, o);
}
});
});
if (!failed) {
console.log(`[All passed]: ${passed}/${allCases}`);
}
})();