數據
[{ "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:動態條件過濾來自於工作中的一個需求
過濾前:
過濾后: