这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>

这JS判断怎么简化,把我给看晕了

其实就是一个过滤功能


回答:

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_xxxo.is_xxx 成对出现
  • op.is_show_xxxtrue 的时候需要判断 o.is_xxx (过滤)
  • 将过滤出来的所有 o.is_xxx&& 组合条件,得到计算结果
  • 最终结果正好与计算结果相反

因为 op.is_show_xxxop.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;

}

这一段中的遍历部分(初始化 resultfor)直接翻译成 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 的重构很方便)

这JS判断怎么简化,把我给看晕了

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 去干的事情,为啥都在用 watchlist 的数据,然后,他这个里面的逻辑,就我个人理解,最核心的就两个点:

  1. 过滤的时候,如果选中了 is_show_xxx 那么 item.is_xxx 就必须为 true
  2. 如果没选中 is_show_xxx,那么 item.is_xxx 不参与是否展示的判断

也说了,有很多这种成对出现的 is_xxxis_show_xxx,所以,简单来说,就两步:

  1. 拿到所有 item 的所有 is_xxx
  2. 判断 is_show_xxx 是否为 false,如果为 false 不参与判断,那么这条 field 直接过,如果为 true,参与判断,再判断一个 item.is_xxx 是否为 true 就可以了,判断的时候,要求所有满足条件的都为 true,所以使用的是 every

然后,还是想多说几句

  1. 代码里面,那个过滤功能,如果只是用来展示,不要修改原始数据, Vue 提供了那么好用的 Computed 不用
  2. 代码能乱成这样,原因肯定是写代码之前就没有想好自己要解决的核心问题所至,建议还是多思考,少动手写,写一行是一行,让每一行代码都有价值
  3. 假如说,最后是需要用到上面的结果做持久化存储的,那就直接从 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

回到顶部