JS对大量数据进行多重过滤的方法_javascript技巧

前言

主要的需求是前端通过 Ajax 从后端取得了大量的数据,需要根据一些条件过滤,首先过滤的方法是这样的:

class Filter {
 filterA(s) {
 let data = this.filterData || this.data;
 this.filterData = data.filter(m => m.a === s);
 }

 filterB(s) {
 let data = this.filterData || this.data;
 this.filterData = data.filter(m => m.b === s);
 }
}

现在迷糊了,觉得这样处理数据不对,但是又不知道该怎么处理。

发现问题

问题就在过滤上,这样固然可以实现多重过滤(先调用 filterA() 再调用 filterB() 就可以实现),但是这个过滤是不可逆的。

假如过滤过程是这样:

f.filterA("a1");
f.filterB("b1");
f.filterA("a2");

本来是希望按 "a1" 和 "b1" 过滤了数据之后,再修改第一个条件为 "a2",但结果却成了空集。

解决问题

发现了问题,就针对性的解决。这个问题既然是因为过滤过程不可逆造成的,那每次都直接从 this.data 开始过滤,而不是从 this.filterData 开始过滤,就能解决问题。如果要这样做,就需要将选择的过滤条件先记录下来。

记录过滤条件

用一个列表记录过滤条件当然是可行的,但是注意对同一个条件的两次过滤是互斥的,只能保留最后一个,所以应该用 HashMap 更为合适。

class Filter {
 constructor() {
 this.filters = {};
 }

 set(key, filter) {
 this.filters[key] = filter;
 }

 getFilters() {
 return Object.keys(this.filters).map(key => this.filters[key]);
 }
}

这种情况下,像上面的过程表示为

f.set("A", m => m.a === "a1");
f.set("B", m => m.b === "b1");
f.set("A", m => m.a === "a1");

let filters = f.getFilters(); // length === 2;

上面第 3 句设置的 filter 覆盖了第 1 句设置的那个。现在再用最后取得的 filters 依次来过滤原数据 this.data,就能得到正确的结果。

有人会觉得 getFilters() 返回的列表不是按 set 的顺序的——的确,这是 HashMap 的特点,无序。不过对于简单条件的判断,不管谁先谁后,结果是一样的。但是对于一些复合条件判断,就可能会有影响。

确实需要的话,可以通过 array 代替 map 来解决一下顺序的问题,但这样查找效率会降低(线性查找)。如果还想解决查找效率的问题,可以用 array + map 来处理。这里就不多说了。

过滤

实际上在使用的时候,每次都 getFilter() 再用一个循环来处理确实比较慢。既然 data 都封装成 Filter 中,可以考虑直接给一个 filter() 方法来送货过滤接口。

class Filter {
 filter() {
 let data = this.data;
 for (let f of this.getFilters()) {
  data = data.filter(f);
 }
 return data;
 }
}

不过这样我觉得效率不太好,尤其是对大量数据的时候。不妨利用一下 lodash 的延迟处理过程。

利用 lodash 的延迟处理

filter() {
 let chain = _(this.data);
 for (let f of this.getFilters()) {
 chain = chain.filter(f);
 }
 return chain.value();
}

lodash 在数据大于 200 的时候会启用延迟处理过程,也就是说,它会处理成一个循环中依次调用每一个 filter,而不是对每一个 filter 进行一次循环。

延迟处理和非延迟处理通过下图可以看出来区别。非延迟处理总共会进行 n(这里 n = 3) 次大循环,产生 n - 1 个中间结果。而延迟处理只会进行一次大循环,没有中间结果产生。

不过说实在的,我不太喜欢为了一点小事多加载一个库,所以干脆自己做个简单的实现

自己实现延迟处理

filter() {
 const filters = this.getFilters();
 return data.filter(m => {
 for (let f of filters) {
  // 如果某个 filter 已经把它过滤掉了,也不用再用后面的 filter 来判断了
  if (!f(m)) {
  return false;
  }
 }
 return true;
 });
}

里面的 for 循环还可以用 Array.prototype.every 来简化:

filter() {
 const filters = this.getFilters();
 return data.filter(m => {
 return filters.every(f => f(m));
 });
}

数据过滤其实并不是多复杂的事情,只要把思路理清楚,搞明白什么数据是需要保留的,什么数据是临时(中间过程)的,什么数据是最终结果……利用 Array.prototype 中的相关方法,或者诸如 lodash 之类的工具,很容易就处理出来了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能有所帮助,如果有疑问大家可以留言交流。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索js过滤数据
, js处理大量数据
js过滤重复数据
javascript xss过滤、javascript 数组过滤、javascript过滤器、php过滤javascript、java 过滤javascript,以便于您获取更多的相关知识。

时间: 2024-08-01 14:59:20

JS对大量数据进行多重过滤的方法_javascript技巧的相关文章

JS实现表格数据各种搜索功能的方法_javascript技巧

本文实例讲述了JS实现表格数据各种搜索功能.可忽略大小写,模糊搜索,多关键搜索.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!DOCTYPE html> <html>  <head>   <meta charset="utf-8">   <title></title>   <script type="text/javascript">    window.onl

js拆分字符串并将分割的数据放到数组中的方法_javascript技巧

本文实例讲述了js拆分字符串并将分割的数据放到数组中的方法.分享给大家供大家参考.具体实现方法如下: var splitArray = new Array(); var string="太平洋.大西洋.印度洋.北冰洋"; var regex = /./; splitArray=string.split(regex); for(i=0; i < splitArray.length; i++){ document.write(splitArray[i] + "<br&

Bootstrap Table从服务器加载数据进行显示的实现方法_javascript技巧

Bootstrap-Table是一个Boostrap的表格插件,能够将JSON数据直接显示在表格中.当然,这需要配置一些参数并进行初始化表格才行.其官方网站地址为:http://bootstrap-table.wenzhixin.net.cn/.里面可以下载使用所需的JS和CSS文件,以及参考文档和例子.         Bootstrap-Table显示数据到表格的方式有两种,一种是客户端(client)模式,一种是服务器(server)模式.         所谓客户端模式,指的是在服务器中

JS中使用变量保存arguments对象的方法_javascript技巧

迭代器(iterator)是一个可以顺序存取数据集合的对象.其一个典型的API是next方法.该方法获得序列中的下一个值. 迭代器示例 题目:希望编写一个便利的函数,它可以接收任意数量的参数,并为这些值建立一个迭代器. 测试代码好下: var it=values(,,,,,,,,); it.next();// it.next();// it.next();// 分析:由于values函数需要接收任意多个参数,这里就需要用到上一节讲到的构建可变参数的函数的方法.然后里面的迭代器对象来遍历argum

JS 动态加载脚本的4种方法_javascript技巧

如果js文件都比较小,还是一个js好,这样可以减少连接数.下面是4种比较常用的方法,大家可以根据情况选择,最后 将会给推荐一个.1.直接document.write 复制代码 代码如下: <script language="javascript"> document.write("<script src='test.js'><\/script>"); </script> 2.动态改变已有script的src属性 复制代

JS传值出现中文参数乱码的解决方法_javascript技巧

本文实例讲述了JS传值出现中文参数乱码的解决方法.分享给大家供大家参考,具体如下: function PopupFK(cNum,type){ var url = "contract!Paying.action"; url = url + "?contract.contractNum="+cNum+"&payingType="+type; // if(isEmpty($(_this).attr("payId"))){ /

js传值后台中文出现乱码的解决方法_javascript技巧

本文实例讲述了js传值后台中文出现乱码的解决方法.分享给大家供大家参考,具体如下: 在"test.jsp"页面中,需要通过js将值传递到后台,后台根据传递的值进行数据查询时,通过test.jsp的js进行编码(标注部分的代码),后台Java解码(注释标注部分为解码),可以解决 test.jsp: <script type="text/JavaScript" charset="UTF-8"> function test() { //下面

JS弹出新窗口被拦截的解决方法_javascript技巧

在Web编程中,使用JS在新窗口打开页面的时候,会遇到被浏览器拦截的情况,那么,我们如何才能让JS打开新窗口不被浏览器阻止呢? 一.问题一 一般情况下,如果直接在js中调用window.open()函数去打开一个新窗口,浏览器会对弹出的窗口进行拦截,因为浏览器会把该窗口认为是弹出广告等用户不想得到的窗体 1.解决方法 把window.open()函数改为由用户主动点击时触发,在超链接里加入onclick事件,这样浏览器就认为是用户想访问这个页面,而不是直接弹出给用户 2.例如: <a href=

js实现网页随机切换背景图片的方法_javascript技巧

本文实例讲述了js实现网页随机切换背景图片的方法.分享给大家供大家参考.具体实现方法如下: 首先要准备一些图像,图像的大小(无论是尺寸大小还是数据大小)要控制好,如果太大,会使用户等不及查看全图就跳出了,如果太小,又会影响页面质量 在script中将这些图像编为一个数组,便于调用.数组的长度当然就是图像的数量. 复制代码 代码如下: var bodyBgs = [];    //创建一个数组变量来存储背景图片的路径 bodyBgs[0] = "images/01.jpg"; bodyB