JS實(shí)現(xiàn)數(shù)組過(guò)濾從簡(jiǎn)單到多條件篩選
在上家公司工作的時(shí)候,有一個(gè)需求是在前端部分完成篩選功能,一次拿到所有數(shù)據(jù),然后根據(jù)條件篩選。通常情況下篩選是后臺(tái)給接口,在數(shù)據(jù)量不大的情況下,也有人可能會(huì)遇到前端篩選這樣的情況,特別寫(xiě)了這篇文章分享給大家,有問(wèn)題請(qǐng)指出,互相學(xué)習(xí)。
一般情況下的單條件篩選,數(shù)組的filter方法就能夠滿足需求,本文討論的重點(diǎn)是多條件下的復(fù)合篩選,并列出了幾個(gè)相關(guān)知識(shí)點(diǎn)。
以下是很多個(gè)🌰🌰🌰🌰
// 這個(gè)是例子中的被篩選數(shù)組
var aim = [
{name:'Anne', age: 23, gender:'female'},
{name:'Leila', age: 16, gender:'female'},
{name:'Jay', age: 19, gender:'male'},
{name:'Mark', age: 40, gender:'male'}
]
單條件單數(shù)據(jù)篩選
根據(jù)單個(gè)名字篩選,用filter方法,判斷name是否為目標(biāo)名字即可
// 根據(jù)單個(gè)名字篩選
function filterByName(aim, name) {
return aim.filter(item => item.name == name)
}
// 輸入 aim 'Leila' 期望輸出為 [{name:'Leila', age: 16, gender:'female'}]
console.log(filterByName(aim,'leila'))
單條件多數(shù)據(jù)篩選
根據(jù)多個(gè)名字篩選,這里是用for循環(huán)遍歷目標(biāo)數(shù)組,然后用find方法找到后push到結(jié)果數(shù)組里,用find方法是重名情況下也能得到想要的結(jié)果。for循環(huán)可以用數(shù)組的一些遍歷方法替代,代碼可以更簡(jiǎn)化,示例就是大概表達(dá)個(gè)意思。
// 根據(jù)多個(gè)名字篩選
function filterByName1(aim, nameArr) {
let result = []
for(let i = 0; i < nameArr.length; i++) {
result.push(aim.find(item => item.name = nameArr[i]))
}
return result
}
// 輸入 aim ['Anne','Jay']
//期望輸出為 [{name:'Anne', age: 23, gender:'female'},{name:'Jay', age: 19, gender:'male'}]
console.log(filterByName1(aim,['Leila','Jay']))
// 有BUG 改進(jìn)后
多條件單數(shù)據(jù)篩選
根據(jù)單個(gè)名字或者單個(gè)年齡篩選,用filter方法,判斷條件之間是或的關(guān)系。
// 根據(jù)名字或者年齡篩選
function filterByName2(aim, name, age) {
return aim.filter(item => item.name == name || item.age == age)
}
console.log(filterByName2(aim,'Leila',19))
多條件多數(shù)據(jù)篩選
我最初是用了很笨的雙for循環(huán)去做,發(fā)現(xiàn)很慢,而且并沒(méi)有達(dá)到預(yù)期的效果。具體的心路歷程已經(jīng)太遙遠(yuǎn),簡(jiǎn)單介紹以下這個(gè)篩選算法。
首先是把篩選條件都塞到一個(gè)對(duì)象里,用object對(duì)象的keys方法獲取到篩選的條件名,及需要篩選的是哪個(gè)條件,是name?age? gender?
然后使用filter方法對(duì)目標(biāo)數(shù)據(jù)進(jìn)行篩選,🌰如下⬇️
根據(jù)名字和年齡多元素篩選
//根據(jù)名字和年齡多元素篩選
export function multiFilter(array, filters) {
const filterKeys = Object.keys(filters)
// filters all elements passing the criteria
return array.filter((item) => {
// dynamically validate all filter criteria
return filterKeys.every(key => {
//ignore when the filter is empty Anne
if(!filters[key].length) return true
return !!~filters[key].indexOf(item[key])
})
})
}
/*
* 這段代碼并非我原創(chuàng),感興趣的可以去原作者那里點(diǎn)個(gè)贊
* 作者是:@author https://gist.github.com/jherax
* 這段代碼里我只加了一行,解決部分篩選條件清空時(shí)候整體篩選失效的問(wèn)題
*/
var filters = {
name:['Leila', 'Jay'],
age:[]
}
/* 結(jié)果:
* [{name: "Leila", age: 16, gender: "female"},
* {name: "Jay", age: 19, gender: "male"}]
*/
例如這里,判斷每條數(shù)據(jù)的name值是否在filters.name數(shù)組里,是的話返回true,判斷filters.age是空數(shù)組的話直接返回true,空數(shù)組是模擬了age條件被清空的情況,我們?nèi)匀荒艿玫秸_的篩選數(shù)據(jù)。
知識(shí)點(diǎn)1: Object.key() 獲取數(shù)組索引或者對(duì)象屬性
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr));
// ["0", "1", "2"]
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj));
// ["0", "1", "2"]
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj));
// ["2", "7", "100"] 猜猜為啥?
知識(shí)點(diǎn)2: js里的falsy
falsy : 0 , false, "", null, undefined, NaN
在判斷語(yǔ)句中,只有上面6種情況會(huì)是false,其余的都是true
var a;
if(a!=null&&typeof(a)!=undefined&&a!=''){
//a有內(nèi)容才執(zhí)行的代碼
}
if(!!a){
//a有內(nèi)容才執(zhí)行的代碼...
}
知識(shí)點(diǎn)3: Array.every 與 Array.some的區(qū)別
我的理解是在遍歷數(shù)組的時(shí)候:
- Array.every的條件是「與」的關(guān)系,全真為真,及條件全為true則為true,有一個(gè)false就返回false
- Array.some的條件是「或」的關(guān)系,有真為真,條件有一個(gè)true就返回true,條件全為false的時(shí)候才返回false
下面舉個(gè)🌰
// 判斷每個(gè)名字都為Anne? let dataEvery = aim.every(item => item.name === 'Anne') // false let dataEvery = aim.some(item => item.name === 'Anne') // true // 判斷每個(gè)名字都是字符串? let dataEvery = aim.every(item => typeof item.name === 'string') // true let dataEvery = aim.some(item => typeof item.name === 'string') // true
知識(shí)點(diǎn)4: 數(shù)組的深拷貝與淺拷貝
最近參與一些前端的面試工作,深拷貝與淺拷貝是我最?lèi)?ài)問(wèn)的問(wèn)題之一。一個(gè)問(wèn)題就考察了數(shù)據(jù)類(lèi)型,數(shù)組操作,遞歸算法等。
因?yàn)閿?shù)組是js里的引用類(lèi)型,單純復(fù)制時(shí)復(fù)制的是其引用關(guān)系。在對(duì)獲取的數(shù)據(jù)進(jìn)行篩選時(shí),我并不希望影響原始數(shù)據(jù),所以我要用到「深拷貝」得到與原始數(shù)據(jù)數(shù)據(jù)結(jié)構(gòu)完全相同又相互獨(dú)立的數(shù)據(jù),而不是只復(fù)制其引用關(guān)系。
// 我常用方法,如果項(xiàng)目很大,不推薦
let obj1 = JSON.parse(JSON.stringify(obj))
// deepclone
function deepClone(o1, o2) {
for (let k in o2) {
if (typeof o2[k] === 'object') {
o1[k] = {};
deepClone(o1[k], o2[k]);
} else {
o1[k] = o2[k];
}
}
}
想一想:遞歸算法的優(yōu)化
這個(gè)知識(shí)點(diǎn)與本文關(guān)系不大。😄 抱歉之前的誤導(dǎo)。
這個(gè)是看掘金小冊(cè)前端面試指南看到的,講算法的時(shí)候提了一下遞歸算法的優(yōu)化,初見(jiàn)的時(shí)候又被驚艷到,還沒(méi)有在項(xiàng)目里用到。感興趣的可以試試,這個(gè)是斐波那契數(shù)列和??梢宰约涸跒g覽器里敲一下,試試不用緩存與用緩存的運(yùn)算次數(shù)差別。
let count = 0;
function fn(n) {
let cache = {};
function _fn(n) {
if (cache[n]) {
return cache[n];
}
count++;
if (n == 1 || n == 2) {
return 1;
}
let prev = _fn(n - 1);
cache[n - 1] = prev;
let next = _fn(n - 2);
cache[n - 2] = next;
return prev + next;
}
return _fn(n);
}
let count2 = 0;
function fn2(n) {
count2++;
if (n == 1 || n == 2) {
return 1;
}
return fn2(n - 1) + fn2(n - 2);
}
到此這篇關(guān)于JS實(shí)現(xiàn)數(shù)組過(guò)濾從簡(jiǎn)單到多條件篩選的文章就介紹到這了,更多相關(guān)JS 數(shù)組過(guò)濾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
小議Function.apply() 之一------(函數(shù)的劫持與對(duì)象的復(fù)制)
小議Function.apply() 之一------(函數(shù)的劫持與對(duì)象的復(fù)制)...2006-11-11
靈活應(yīng)用js調(diào)試技巧解決樣式問(wèn)題的步驟分享
在很多時(shí)候,前端開(kāi)發(fā)人員使用JS腳本,對(duì)頁(yè)面Dom結(jié)構(gòu)或者是樣式做出了修改,會(huì)造成一些意想不到的bug2012-03-03
Webpack框架核心概念(知識(shí)點(diǎn)整理)
webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的模塊打包器(module bundler)。這篇文章主要介紹了Webpack框架核心概念(知識(shí)點(diǎn)整理),需要的朋友可以參考下2017-12-12
layui遞歸實(shí)現(xiàn)動(dòng)態(tài)左側(cè)菜單
這篇文章主要為大家詳細(xì)介紹了layui遞歸實(shí)現(xiàn)動(dòng)態(tài)左側(cè)菜單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
layer.alert自定義關(guān)閉回調(diào)事件的方法
今天小編就為大家分享一篇layer.alert自定義關(guān)閉回調(diào)事件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
JavaScript在瀏覽器標(biāo)題欄上顯示當(dāng)前日期和時(shí)間的方法
這篇文章主要介紹了JavaScript在瀏覽器標(biāo)題欄上顯示當(dāng)前日期和時(shí)間的方法,實(shí)例分析了javascript操作時(shí)間及DOM節(jié)點(diǎn)實(shí)現(xiàn)定時(shí)觸發(fā)的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03
JavaScript中json對(duì)象和string對(duì)象之間相互轉(zhuǎn)化
json對(duì)象和string對(duì)象之間的轉(zhuǎn)化已經(jīng)成為了大家耳熟能詳?shù)脑掝},本人今天就多啰嗦一些他們之間的故事,如有不對(duì)之處,還請(qǐng)各位海涵呢?不多說(shuō)了直切主題2012-12-12

