数据
[{ "name": "张三", "score": 153 }, { "name": "李四", "score": 206 }, { "name": "王五", "score": 68.5 }, { "name": "王六", "score": 83.5 }]
需求:需要根据动态的条件来对数据进行查询。
步骤1:定义过滤器并初始化,比如我们要查询王五以6分开头的数据,条件定义:`姓名 equal 王五 && 成绩 beginWith 6`
/// 过滤器集合,格式:{field:'',relationType:'',value: ''} /// field - 用于过滤的属性(字段) /// relationType - 关联关系(比较方式),可选值有equal(等于)、notEqual(不等于)、like(模糊匹配)、beginWith(以它开头)、endWith(以它结尾) /// value - 用于被比较的过滤器值 const filters = [] filters.push({ field: 'name', relationType: 'equal', value: '王五' }) filters.push({ field: 'score', relationType: 'beginWith', value: '6' })
步骤2:定义一个通用的过滤函数,过滤函数传递2个参数,第1个是需要被过滤的数据源,第2个是过滤器集合,函数返回值是过滤后的数据源
// 过滤数据源 function filteringDataSources (source, filters) { // 动态表达式集合,用于存储判断某个对象是否满足条件的函数 const expressions = [] // 遍历过滤器集合,动态添加表达式函数 filters.forEach(item => { // 添加表达式函数,参数为数组的每个数据对象 expressions.push((obj) => { // 是否符合条件 let isFit = false // 数据对象对应的属性值 let objValue = '' // 用于被比较的过滤器值 const compareValue = item.value // 判断数据对象是否存在用于过滤的属性,如果不存在直接判定为不符合条件 if (typeof (obj[item.field]) === 'undefined') { isFit = false return isFit } // 获取数据对象用于比较的属性值,统一转为字符串类型,便于比较 objValue = String(obj[item.field]) // 判断逻辑 if (item.relationType === 'equal') { // 等于 isFit = objValue === compareValue } else if (item.relationType === 'notEqual') { // 不等于 isFit = objValue !== compareValue } else if (item.relationType === 'like') { // 模糊匹配 isFit = objValue.includes(compareValue) } else if (item.relationType === 'beginWith') { // 以它开头 isFit = objValue.startsWith(compareValue) } else if (item.relationType === 'endWith') { // 以它结尾 isFit = objValue.endsWith(compareValue) } // 返回当前表达式是否符合条件 return isFit }) }) // 遍历数据源 source = source.filter((item, index) => { // 是否符合条件 let isFit = true // 遍历表达式集合,循环判断每个用于过滤的表达式函数是否符合 for (let index = 0; index < expressions.length; index++) { // 获取表达式函数 const expression = expressions[index] // 调用表达式函数,获取结果 const result = expression(item) // 如果结果为false,则终止表达式集合的遍历(即有一个条件不符合,则该条数据则被判定不满足条件) if (!result) { isFit = false break } } // 返回当前数据对象是否符合条件,不符合条件则被过滤掉,不会出现在最终数据中 return isFit }) // 返回过滤后的数据源 return source }
步骤3:调用过滤函数得到结果
if (filters.length > 0) { source = filteringDataSources(source, filters) }
结果:
Array(1) 0: {name(test_scores): "王五", score(test_scores): 68.5} length: 1
完整代码:
// 过滤数据源 function filteringDataSources (source, filters) { // 动态表达式集合,用于存储判断某个对象是否满足条件的函数 const expressions = [] // 遍历过滤器集合,动态添加表达式函数 filters.forEach(item => { // 添加表达式函数,参数为数组的每个数据对象 expressions.push((obj) => { // 是否符合条件 let isFit = false // 数据对象对应的属性值 let objValue = '' // 用于被比较的过滤器值 const compareValue = item.value // 判断数据对象是否存在用于过滤的属性,如果不存在直接判定为不符合条件 if (typeof (obj[item.field]) === 'undefined') { isFit = false return isFit } // 获取数据对象用于比较的属性值,统一转为字符串类型,便于比较 objValue = String(obj[item.field]) // 判断逻辑 if (item.relationType === 'equal') { // 等于 isFit = objValue === compareValue } else if (item.relationType === 'notEqual') { // 不等于 isFit = objValue !== compareValue } else if (item.relationType === 'like') { // 模糊匹配 isFit = objValue.includes(compareValue) } else if (item.relationType === 'beginWith') { // 以它开头 isFit = objValue.startsWith(compareValue) } else if (item.relationType === 'endWith') { // 以它结尾 isFit = objValue.endsWith(compareValue) } // 返回当前表达式是否符合条件 return isFit }) }) // 遍历数据源 source = source.filter((item, index) => { // 是否符合条件 let isFit = true // 遍历表达式集合,循环判断每个用于过滤的表达式函数是否符合 for (let index = 0; index < expressions.length; index++) { // 获取表达式函数 const expression = expressions[index] // 调用表达式函数,获取结果 const result = expression(item) // 如果结果为false,则终止表达式集合的遍历(即有一个条件不符合,则该条数据则被判定不满足条件) if (!result) { isFit = false break } } // 返回当前数据对象是否符合条件,不符合条件则被过滤掉,不会出现在最终数据中 return isFit }) // 返回过滤后的数据源 return source } let source = [{ 'name': '张三', 'score': 153 }, { 'name': '李四', 'score': 206 }, { 'name': '王五', 'score': 68.5 }, { 'name': '王六', 'score': 83.5 }] /// 过滤器集合,格式:{field:'',relationType:'',value: ''} /// field - 用于过滤的属性(字段) /// relationType - 关联关系(比较方式),可选值有equal(等于)、notEqual(不等于)、like(模糊匹配)、beginWith(以它开头)、endWith(以它结尾) /// value - 用于被比较的过滤器值 const filters = [] filters.push({ field: 'name', relationType: 'equal', value: '王五' }) filters.push({ field: 'score', relationType: 'beginWith', value: '6' }) source = filteringDataSources(source, filters) console.log(source)
PS:动态条件过滤来自于工作中的一个需求
过滤前:
过滤后: