这JS判断怎么简化,把我给看晕了
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;
};
----------------------完整-----------------------------
<template><div style="margin-bottom: 20px; margin-top: 20px;">
<label><input type="checkbox" v-model="show_gl.is_show_gl1" /> 过滤一</label>
<label><input type="checkbox" v-model="show_gl.is_show_gl2" /> 过滤二</label>
<label><input type="checkbox" v-model="show_gl.is_show_gl3" /> 过滤三</label>
</div>
<div>
<table>
<template v-for="(item, index) in list" :key="index">
<tr v-if="item.is_show">
<td>{{item.id}}</td>
<td>{{item.is_gl1}}</td>
<td>{{item.is_gl2}}</td>
<td>{{item.is_gl3}}</td>
</tr>
</template>
</table>
</div>
</template>
<script>
import {reactive, ref, watch} from "vue";
export default {
name: "Test",
setup() {
const show_gl = reactive({
is_show_gl1: false,
is_show_gl2: false,
is_show_gl3: false,
});
const list = ref([
{
id: 1,
is_gl1: false,
is_gl2: true,
is_gl3: false,
is_show: true,
},
{
id: 2,
is_gl1: false,
is_gl2: false,
is_gl3: true,
is_show: true,
},
{
id: 3,
is_gl1: false,
is_gl2: true,
is_gl3: false,
is_show: true,
},
{
id: 4,
is_gl1: true,
is_gl2: true,
is_gl3: true,
is_show: true,
},
{
id: 5,
is_gl1: false,
is_gl2: true,
is_gl3: false,
is_show: true,
},
{
id: 6,
is_gl1: true,
is_gl2: false,
is_gl3: false,
is_show: true,
},
]);
watch(show_gl, () => {
for (let i = 0; i < list.value.length; i++) {
if (show_gl.is_show_gl1 || show_gl.is_show_gl2 || show_gl.is_show_gl3) {
if (show_gl.is_show_gl1 && show_gl.is_show_gl2 && show_gl.is_show_gl3) {
if (list.value[i].is_gl1 && list.value[i].is_gl2 && list.value[i].is_gl3) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl1 && show_gl.is_show_gl2) {
if (list.value[i].is_gl1 && list.value[i].is_gl2) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl1 && show_gl.is_show_gl3) {
if (list.value[i].is_gl1 && list.value[i].is_gl3) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl2 && show_gl.is_show_gl3) {
if (list.value[i].is_gl2 && list.value[i].is_gl3) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl1) {
if (list.value[i].is_gl1) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl2) {
if (list.value[i].is_gl2) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
} else if (show_gl.is_show_gl3) {
if (list.value[i].is_gl3) {
list.value[i].is_show = true;
} else {
list.value[i].is_show = false;
}
}
} else {
list.value[i].is_show = true;
}
}
});
return {show_gl, list}
},
}
</script>
<style scoped>
table, td {
border: solid 1px #666;
}
td {
padding: 5px 10px;
}
label {
margin-right: 20px;
}
</style>
其实就是一个过滤功能
回答:
const isDel = (op, o) => { // 查询字段关联
const dicWhereRel = {
is_show_gl1: "is_gl1",
is_show_gl2: "is_gl2",
is_show_gl3: "is_gl3"
};
//filter 筛选需要的查询字段; every 字段值是否相等,都相等为true,否则为false
return Object.entries(op)
.filter(([key, val]) => val)
.every(([key, val]) => o[dicWhereRel[key]] == val);
};
Vue.watch(show_gl, () => {
list.value.forEach((item) => {
item.is_show = isDel(show_gl, item);
});
});
https://codepen.io/1567887123...
回答:
2021-08-17 更新
昨天有点忙,只留了代码。今天来补个解释。
观察问题,总结规律:
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}`);
}
})();
全部通过
[All passed]: 64/64
回答:
补充一下:就我看提问者上面的这代码质量,他的实现肯定是有问题的,决对不是真正解决他需求的最优解,感觉提问者可以把你的需求提出来。
const filteredList = Vue.computed(() => list.value.filter(item => Object.keys(item)
.filter(key => key.startsWith('is_') && key !== 'is_show')
.every(key => !show_gl[key.replace('_', '_show_')] || item[key])));
我是真不知道为什么会给我推这个问题,看了大家答案,你们是不是都被提问题的人带偏了?他这很明显就是一个 VUE 项目,一个应该是 computed
去干的事情,为啥都在用 watch
改 list
的数据,然后,他这个里面的逻辑,就我个人理解,最核心的就两个点:
- 过滤的时候,如果选中了
is_show_xxx
那么item.is_xxx
就必须为true
- 如果没选中
is_show_xxx
,那么item.is_xxx
不参与是否展示的判断
也说了,有很多这种成对出现的 is_xxx
和 is_show_xxx
,所以,简单来说,就两步:
- 拿到所有
item
的所有is_xxx
- 判断
is_show_xxx
是否为false
,如果为false
不参与判断,那么这条field
直接过,如果为true
,参与判断,再判断一个item.is_xxx
是否为true
就可以了,判断的时候,要求所有满足条件的都为true
,所以使用的是every
然后,还是想多说几句
- 代码里面,那个过滤功能,如果只是用来展示,不要修改原始数据,
Vue
提供了那么好用的Computed
不用 - 代码能乱成这样,原因肯定是写代码之前就没有想好自己要解决的核心问题所至,建议还是多思考,少动手写,写一行是一行,让每一行代码都有价值
- 假如说,最后是需要用到上面的结果做持久化存储的,那就直接从
filteredList
里面拿数据就可以了(只要是这个list
里面的,is_show
就一定为true
,否则就为false
,提交的时候批量改一下这个值就可以了)
回答:
似乎是要一一对应的意思
我拿位运算口胡了个
const isDel = (op, o) => { return isDel.state(op, "is_show_") === isDel.state(o, "is_")
}
isDel.state = (x, prefix) => {
let s = 0;
[ "lock", "sf", "bz" ].forEach((k, i) => {
if (x[prefix + k]) s = s | 1 << i
})
return s
}
似乎是逻辑蕴含的意思,我再口胡一个
const idDel = (o1, o2) => { const p1 = "is_show_", p2 = "is_" // 前缀
return [ "gl1", "gl2", "gl3" ].every(f => ! o1[p1 + f] || o2[p2 + f]))
}
// 用的时候这样
(show_gl) => {
for (let i = 0; i < list.value.length; i++) {
list.value[i].is_show = isDel(show_gl, list.value[i])
}
}
回答:
思路:找到list和showObject的字段共同点,便于进行判断,这里共同点就是他们结尾的字符串一样(_gl1),这个你可以根据你的业务场景修改,然后就是你这里的筛选是取并集的,所以在第二层判断那里我把show用数组存起来了,在外层用reduce计算一次并集,把最后的计算结果赋值就可以了,还有一点就是,你这里如果没有筛选,默认就是全显示的,所有reduce的默认值给的是true
watch(show_gl, () => { for (let i = 0; i < list.value.length; i++) {
const listKeys = Object.keys(list.value[i])
const is_show = []
for(let key in show_gl) {
if (show_gl.hasOwnProperty(key) && show_gl[key]) {
// key.slice(-4) -> _gl1
const current = listKeys.find(v => v.endsWith(key.slice(-4)))
is_show.push(list.value[i][current] ?? false)
}
}
list.value[i].is_show = is_show.reduce((a, b) => a && b, true)
}
});
回答:
const isRemove = (op, o) => (op.is_show_lock && !o.is_lock) || (op.is_show_sf && !o.is_sf) || (op.is_show_bz && !o.is_bz)
之前的回答有误,没有验证,凭感觉写的,这次应该没问题了。借用了@边城 的测试。
主要就是运用布尔代数简化表达式,提取了true的情况,列出所有true的布尔逻辑然后根据法则做运算即可
布尔代数运算律
回答:
watch(show_gl, () => {
const transformParams = (key) => { const map = {
is_show_gl1: 'is_gl1',
is_show_gl2: 'is_gl2',
is_show_gl3: 'is_gl3',
}
return map[key]
}
const activeKey = Object.keys(show_gl).filter(key => show_gl[key]).map(transformParams)
list.value.map(item => {
item.is_show = activeKey.map(key => item[key]).every(Boolean)
})
});
以上是 这JS判断怎么简化,把我给看晕了 的全部内容, 来源链接: utcz.com/p/936118.html