成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript中對大量數據的多重過濾

開發 前端
數據過濾其實并不是多復雜的事情,只要把思路理清楚,搞明白什么數據是需要保留的,什么數據是臨時(中間過程)的,什么數據是最終結果……利用 Array.prototype 中的相關方法,或者諸如 lodash 之類的工具,很容易就處理出來了。

所有代碼使用 ES2015 語法,需要 ES5 語法的可以用 Babel - Try it out 或者 TypeScript Playground 翻譯。

問題提出

今天有朋友問我一個問題,前端通過 Ajax 從后端取得了大量的數據,需要根據一些條件過濾,過濾的方法是這樣的:

  1. class Filter { 
  2.     filterA(s) { 
  3.         let data = this.filterData || this.data; 
  4.         this.filterData = data.filter(m => m.a === s); 
  5.     } 
  6.      
  7.     filterB(s) { 
  8.         let data = this.filterData || this.data; 
  9.         this.filterData = data.filter(m => m.b === s); 
  10.     } 
  11.  

現在迷糊了,覺得這樣處理數據不對,但是又不知道該怎么處理。

發現問題

問題就在過濾上,這樣固然可以實現多重過濾(先調用 filterA() 再調用 filterB() 就可以實現),但是這個過濾是不可逆的。假如過濾過程是這樣:

  1. f.filterA("a1"); 
  2. f.filterB("b1"); 
  3. f.filterA("a2");  

本來是希望按 "a1" 和 "b1" 過濾了數據之后,再修改***個條件為 "a2",但結果卻成了空集。

解決問題

發現了問題,就針對性的解決。這個問題既然是因為過濾過程不可逆造成的,那每次都直接從 this.data 開始過濾,而不是從this.filterData 開始過濾,就能解決問題。如果要這樣做,就需要將選擇的過濾條件先記錄下來。

記錄過濾條件

用一個列表記錄過濾條件當然是可行的,但是注意對同一個條件的兩次過濾是互斥的,只能保留***一個,所以應該用 HashMap 更為合適。 

  1. class Filter { 
  2.     constructor() { 
  3.         this.filters = {}; 
  4.     } 
  5.  
  6.     set(key, filter) { 
  7.         this.filters[key] = filter; 
  8.     } 
  9.  
  10.     getFilters() { 
  11.         return Object.keys(this.filters).map(key => this.filters[key]); 
  12.     } 
  13.  

這種情況下,像上面的過程表示為

  1. f.set("A", m => m.a === "a1"); 
  2. f.set("B", m => m.b === "b1"); 
  3. f.set("A", m => m.a === "a1"); 
  4. let filters = f.getFilters(); // length === 2;  

上面第 3 句設置的 filter 覆蓋了第 1 句設置的那個。現在再用***取得的 filters 依次來過濾原數據 this.data,就能得到正確的結果。

有人會覺得 getFilters() 返回的列表不是按 set 的順序的——的確,這是 HashMap 的特點,無序。不過對于簡單條件的判斷,不管誰先誰后,結果是一樣的。但是對于一些復合條件判斷,就可能會有影響。

確實需要的話,可以通過 array 代替 map 來解決一下順序的問題,但這樣查找效率會降低(線性查找)。如果還想解決查找效率的問題,可以用 array + map 來處理。這里就不多說了。

過濾

實際上在使用的時候,每次都 getFilter() 再用一個循環來處理確實比較慢。既然 data 都封裝成 Filter 中,可以考慮直接給一個filter() 方法來送貨過濾接口。

  1. class Filter { 
  2.     filter() { 
  3.         let data = this.data; 
  4.         for (let f of this.getFilters()) { 
  5.             data = data.filter(f); 
  6.         } 
  7.         return data; 
  8.     } 
  9.  

不過這樣我覺得效率不太好,尤其是對大量數據的時候。不妨利用一下 lodash 的延遲處理過程。

利用 lodash 的延遲處理

  1. filter() { 
  2.     let chain = _(this.data); 
  3.     for (let f of this.getFilters()) { 
  4.         chain = chain.filter(f); 
  5.     } 
  6.     return chain.value(); 
  7.  

lodash 在數據大于 200 的時候會啟用延遲處理過程,也就是說,它會處理成一個循環中依次調用每一個 filter,而不是對每一個 filter 進行一次循環。

延遲處理和非延遲處理通過下圖可以看出來區別。非延遲處理總共會進行 n(這里 n = 3) 次大循環,產生 n - 1 個中間結果。而延遲處理只會進行一次大循環,沒有中間結果產生。

 

 

 

不過說實在的,我不太喜歡為了一點小事多加載一個庫,所以干脆自己做個簡單的實現

自己實現延遲處理

  1. filter() { 
  2.     const filters = this.getFilters(); 
  3.     return data.filter(m => { 
  4.         for (let f of filters) { 
  5.             // 如果某個 filter 已經把它過濾掉了,也不用再用后面的 filter 來判斷了 
  6.             if (!f(m)) { 
  7.                 return false
  8.             } 
  9.         } 
  10.         return true
  11.     }); 
  12.  

里面的 for 循環還可以用 Array.prototype.every 來簡化:

  1. filter() { 
  2.     const filters = this.getFilters(); 
  3.     return data.filter(m => { 
  4.         return filters.every(f => f(m)); 
  5.     }); 
  6.  

數據過濾其實并不是多復雜的事情,只要把思路理清楚,搞明白什么數據是需要保留的,什么數據是臨時(中間過程)的,什么數據是最終結果……利用 Array.prototype 中的相關方法,或者諸如 lodash 之類的工具,很容易就處理出來了。

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2011-03-21 12:41:41

JavaScript

2015-09-14 15:23:44

JavaScriptfunction

2011-03-22 09:49:15

JavaScript

2024-01-22 09:41:05

MongoDB索引

2025-01-21 15:20:14

2021-03-09 09:06:41

漏洞數據安全數據

2016-04-11 09:36:45

軟件定義網絡SDN

2019-08-06 07:17:37

2017-08-22 11:30:15

LinuxWireshark過濾數據包

2009-09-10 15:56:12

多重數據模型集合

2022-11-17 08:00:18

JavaScript錯誤性能

2010-10-09 15:31:51

JavaScriptCookie

2022-12-15 08:00:38

JavaScript錯誤性能

2014-05-29 17:11:59

優化鏈接

2025-02-17 11:24:26

2016-09-18 20:53:16

JavaScript閉包前端

2021-01-06 08:03:00

JavaScript數據結構

2024-12-06 14:34:00

Spring過濾器

2010-09-09 14:25:32

2019-05-29 07:31:15

物聯網數據IOT
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人一区在线 | 日韩欧美精品在线播放 | 精品视频一区二区 | 天天躁日日躁狠狠躁白人 | 黑人巨大精品 | 神马影院一区二区三区 | 免费亚洲视频 | 久久国产精品视频免费看 | 欧美 日韩 中文 | 日韩一区二区在线观看视频 | 中文字幕在线网 | 自拍偷拍第1页 | 亚洲成人av | 日产精品久久久一区二区福利 | 夜夜骑首页 | 激情欧美一区二区三区中文字幕 | 男人的天堂中文字幕 | 天天天操天天天干 | 欧美乱大交xxxxx另类电影 | 伊人网综合在线 | 日本在线中文 | 国产精品视频综合 | 中文字幕一区二区在线观看 | 久久国产精品-久久精品 | 91黄在线观看 | 国产91精品久久久久久久网曝门 | 久久一区二区三区免费 | 亚洲第一中文字幕 | 欧美精品成人 | 亚洲欧美bt | 99re66在线观看精品热 | 亚洲九九 | 红桃成人在线 | 欧美影院久久 | 国产精品国产成人国产三级 | 97色在线视频 | 91视频入口 | 美女天堂在线 | 黄a网站| 自拍偷拍第一页 | 亚洲国产情侣 |