js精準查詢與模糊查詢,總有一種適合你的需求

二十七刻發表於2020-04-03

隨著vuereact在實際開發中應運越來越廣泛,前端們處理資料的需求越來越多。這篇文章就討論一下輕量級列表的搜尋功能。當伺服器的同事將所有資料返回到前端時,前端來做按條件查詢,可以減少向伺服器傳送請求的次數,從而大大的提高效能。本文涉及多種方式的查詢。下面先看程式碼,在說知識點:

// 測試用的資料
staff: [
    {name: "April", job: "programmer", age: "18", hobby: "study"},
    {name: "Shawn", job: "student", age: "8", hobby: "study"},
    {name: "Leo", job: "teacher", age: "28", hobby: "play"},
    {name: "Todd", job: "programmer", age: "19", hobby: "sleep"},
    {name: "Scoot", job: "cook", age: "38", hobby: "paintting"},
]

複製程式碼

單條件精準查詢

/*** 
* @param {Object} lists 所有資料
* @param {string} key 需要查詢的資料的鍵值
* @param {string} value 需要查詢的值
*/
searchKeyValue(lists,key,value) {
     let res = lists.filter(item => item[key] == value);
     return res
},
// 函式執行 在 “staff” 物件中查詢 “job” 值為 “programmer” 的資料
this.searchKeyValue(staff,"job","programmer")
複製程式碼

單條件多值精準查詢

/**
* @param {Object} lists 所有資料
* @param {string} key 需要查詢的資料的鍵值
* @param {Array} valueArr 需要查詢的值
*/
searchKeyValues(lists,key,valueArr){
     let res = lists.filter(item => valueArr.find(i => i === item[key]))
     return res;
},
// 函式執行 在 “staff” 物件中查詢 “job” 值為 “programmer” 和 “student” 的資料
this.searchKeyValues(staff,"job",['programmer','student'])
複製程式碼

多條件準查詢

/**
* @param {Object} lists 所有資料
* @param {Object} filters 需要查詢的資料
*/
searchKeysValue(lists, filters) {
    let resArr = [];
    lists.filter(item => {
        for (let i in filters) {
            if (item[i] == filters[i]) {
                let res = item;
                resArr.push(res)
            }
        }
    });
    return resArr
},
// 函式執行 在 “staff” 物件中查詢 “name” 值為 “April” 和 “hobby” 值為 “study” 的資料
// 注:該方法第二個引數是個物件
let filters = {
    name: "April",
    hobby: "study"
}
this.searchKeysValue(staff, filters)
複製程式碼

多條件多值精準查詢

 /**
 * @param {Object} lists 所有資料
 * @param {Object} filters 需要查詢的資料
 */
 searchKeysValues(lists, filters) {
     let resArr = [];
     lists.filter((item) => {
         for (let i in filters) {
             for (let j of filters[i]) {
                 if (item[i] == j) {
                     resArr.push(item)
                 }
             }
         }
     })
 },
// 函式執行 在 “staff” 物件中查詢 “age” 值為 “8”或“18” 和 “hobby” 值為 “play”或“sleep” 的資料
// 注:該方法第二個引數是個物件,鍵對應的值是個多值的陣列
let filters = {
    age:[8,18],
    hobby:["play","sleep"]
}
this.searchKeysValues(staff,filters)
複製程式碼

涉及的知識點

filter()方法用於過濾陣列元素。該方法建立一個新陣列, 其中包含通過所提供函式實現的測試的所有元素。filter()不會對空陣列進行檢測,也不會改變原始陣列。語法如下:

var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
/** 
 * callback 用來測試陣列的每個元素的函式。返回 true 表示該元素通過測試,保留該元素,false 則不保留。
 * thisArg 執行 callback 時,用於 this 的值。
 */
複製程式碼

find()方法用於返回陣列中滿足提供的測試函式的第一個元素的值。否則返回 undefined。對於空陣列,函式是不會執行的。該方法沒有改變陣列的原始值。語法如下:

arr.find(callback[, thisArg])
// callback 在陣列每一項上執行的函式。
// thisArg可選 執行回撥時用作this 的物件。
複製程式碼

綜上所述:

  • 相同:findfilter 都是不改變原陣列的方法,都不會對空陣列進行檢測。

  • 區別:find只查出第一個符合條件的結果像例子裡是直接返回了一個物件而不是陣列

,而filter返回全部結果仍然是陣列。

上面說到的都是按欄位的關鍵字精準的去查詢對應的資料,當需求變為模糊查詢呢?這個時候字串的indexof方法、includes()和正規表示式就派上了用場。

indexof()模糊查詢

 /** * @param {Object} lists 所有資料 
 * @param {string} keyWord 查詢的關鍵詞
 */
 selectMatchItem(lists, keyWord) {
    let resArr = [];
    lists.filter(item => {
        for(let i in item){
            if (item[i].indexOf(keyWord) >= 0) {
                resArr.push(item);
            }
        }
    })
    return resArr;
 },
 // 函式執行 在 “staff” 物件中查詢 包含 “coot” 的資料。
this.selectMatchItem(staff,'coot')
複製程式碼

indexof()多值模糊查詢

/**
* @param {Object} lists 所有資料
* @param {Array} keyWord 查詢的關鍵詞
*/
selectMatchItems(lists, keyWords) {
    let resArr = [];
    lists.filter(item => keyWords.find(keyWord => {
        for(let i in item){
            if (item[i].indexOf(keyWord) >= 0) {
                resArr.push(item);
            }
        }
    }))
    return resArr;
}
// 函式執行 在 “staff” 物件中查詢 包含 “coot”或者“8” 的資料。
this.selectMatchItems(staff,['odd','8'])
複製程式碼

因為多值模糊查詢的原理都是一樣,一下的方法將不再贅述。

includes()模糊查詢

/**
* @param {Object} lists 所有資料
* @param {Object} keyWord 查詢的關鍵詞
*/
selectMatchItem(lists, keyWord) {
    let resArr = [];
    lists.filter(item => {
        for(let i in item){
            if (item[i].includes(keyWord)) {
                resArr.push(item);
            }
        }
    })
    return resArr;
},
// 函式執行 在 “staff” 物件中查詢 包含 “coot” 的資料。
this.selectMatchItem(staff,'coot')
複製程式碼

emmm...此處就不得不問indexof()includes()有啥子區別???

  • indexof()是es5的方法,該方法返回在陣列/字串中可以找到一個給定元素的第一個索引,如果不存在,則返回-1。

  • includes()是es6的方法,該方法用來判斷一個陣列是否包含一個指定的值,根據情況,如果包含則返回 true,否則返回false。

    再看下圖:查詢的值碰巧是NaN呢?

    js精準查詢與模糊查詢,總有一種適合你的需求

    結果indexof()返回-1,includes()返回true。

  • includes()更加完善,且語義化更強。

正則匹配模糊查詢

/**
* @param {Object} lists 所有資料
* @param {Object} keyWord 查詢的關鍵詞
*/
selectMatchItem(lists, keyWord) {
    let reg =  new RegExp(keyWord);
    let resArr = [];
    lists.filter(item => {
        for(let i in item){
            if (reg.test(item[i])) {
                resArr.push(item);
            }
        }
    })
    return resArr;
},
// 函式執行 在 “staff” 物件中查詢 包含 “8” 的資料。
this.selectMatchItem(staff,'8')
複製程式碼

這幾個方法在效能上差不多。但是test()方法因為使用到了正規表示式,所以能夠實現的功能會比較強大,寫出來的程式碼也更加簡潔。打個比方,在不區分大小寫的模糊搜尋條件下, test 方法只需在正規表示式中新增修飾符 i 即可實現不區分大小寫,而其它方法則要通過多次的方法呼叫和邏輯運算子才能實現效果。當然方法還有很多,選擇適合的才是最好的。

相關文章