JS中的数组过滤,从简单筛选到多条件筛选
栏目: JavaScript · 发布时间: 6年前
内容简介:在上家公司工作的时候,有一个需求是在前端部分完成筛选功能,一次拿到所有数据,然后根据条件筛选。通常情况下筛选是后台给接口,在数据量不大的情况下,也有人可能会遇到前端筛选这样的情况,特别写了这篇文章分享给大家,有问题请指出,互相学习。一般情况下的单条件筛选,数组的filter方法就能够满足需求,本文讨论的重点是多条件下的复合筛选,并列出了几个相关知识点。以下是很多个:chestnut::chestnut::chestnut::chestnut:
在上家公司工作的时候,有一个需求是在前端部分完成筛选功能,一次拿到所有数据,然后根据条件筛选。通常情况下筛选是后台给接口,在数据量不大的情况下,也有人可能会遇到前端筛选这样的情况,特别写了这篇文章分享给大家,有问题请指出,互相学习。
一般情况下的单条件筛选,数组的filter方法就能够满足需求,本文讨论的重点是多条件下的复合筛选,并列出了几个相关知识点。
以下是很多个:chestnut::chestnut::chestnut::chestnut:
// 这个是例子中的被筛选数组 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'} ] 复制代码
单条件单数据筛选
根据单个名字筛选,用filter方法,判断name是否为目标名字即可
// 根据单个名字筛选 function filterByName(aim, name) { return aim.filter(item => item.name == name) } // 输入 aim 'Leila' 期望输出为 {name:'Leila', age: 16, gender:'female'} console.log(filterByName(aim,'leila')) 复制代码
单条件多数据筛选
根据多个名字筛选,这里是用for循环遍历目标数组,然后用find方法找到后push到结果数组里,用find方法是重名情况下也能得到想要的结果。for循环可以用数组的一些遍历方法替代,代码可以更简化,示例就是大概表达个意思。
// 根据多个名字筛选 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 改进后 复制代码
多条件单数据筛选
根据单个名字或者单个年龄筛选,用filter方法,判断条件之间是或的关系。
// 根据名字或者年龄筛选 function filterByName2(aim, name, age) { return aim.filter(item => item.name == name || item.age == age) } console.log(filterByName2(aim,'Leila',19)) 复制代码
多条件多数据筛选
我最初是用了很笨的双for循环去做,发现很慢,而且并没有达到预期的效果。具体的心路历程已经太遥远,简单介绍以下这个筛选算法。
首先是把筛选条件都塞到一个对象里,用object对象的keys方法获取到筛选的条件名,及需要筛选的是哪个条件,是name?age? gender?
然后使用filter方法对目标数据进行筛选,:chestnut:如下:arrow_down:
根据名字和年龄多元素筛选
//根据名字和年龄多元素筛选 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]) }) }) } /* * 这段代码并非我原创,感兴趣的可以去原作者那里点个赞 * 作者是:@author https://gist.github.com/jherax * 这段代码里我只加了一行,解决部分筛选条件清空时候整体筛选失效的问题 */ var filters = { name:['Leila', 'Jay'], age:[] } /* 结果: * [{name: "Leila", age: 16, gender: "female"}, * {name: "Jay", age: 19, gender: "male"}] */ 复制代码
例如这里,判断每条数据的name值是否在filters.name数组里,是的话返回true,判断filters.age是空数组的话直接返回true,空数组是模拟了age条件被清空的情况,我们仍然能得到正确的筛选数据。
知识点1: Object.key() 获取数组索引或者对象属性
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"] 猜猜为啥? 复制代码
知识点2: js里的falsy
falsy: 0 , false, "", null, undefined, NaN
在判断语句中,只有上面6种情况会是false,其余的都是true
var a; if(a!=null&&typeof(a)!=undefined&&a!=''){ //a有内容才执行的代码 } if(!!a){ //a有内容才执行的代码... } 复制代码
知识点3: Array.every 与 Array.some的区别
我的理解是在遍历数组的时候:
Array.every的条件是「与」的关系,全真为真,及条件全为true则为true,有一个false就返回false
Array.some的条件是「或」的关系,有真为真,条件有一个true就返回true,条件全为false的时候才返回false
下面举个:chestnut:
// 判断每个名字都为Anne? let dataEvery = aim.every(item => item.name === 'Anne') // false let dataEvery = aim.some(item => item.name === 'Anne') // true // 判断每个名字都是字符串? let dataEvery = aim.every(item => typeof item.name === 'string') // true let dataEvery = aim.some(item => typeof item.name === 'string') // true 复制代码
知识点4: 数组的深拷贝与浅拷贝
最近参与一些前端的面试工作,深拷贝与浅拷贝是我最爱问的问题之一。一个问题就考察了数据类型,数组操作,递归算法等。
因为数组是js里的引用类型,单纯复制时复制的是其引用关系。在对获取的数据进行筛选时,我并不希望影响原始数据,所以我要用到「深拷贝」得到与原始数据数据结构完全相同又相互独立的数据,而不是只复制其引用关系。
// 我常用方法,如果项目很大,不推荐 let obj1 = JSON.parse(JSON.stringify(obj)) // 看掘金小册前端面试指南看到的 // 这个加缓存的方法看到的时候很惊艳,我知道递归可以解决,但是没有想过加缓存优化 function fn(n) { let cache = {}; function _fn(n) { if (cache[n]) { return cache[n]; } 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); } // 常规无缓存的方法 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]; } } } 复制代码
完!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- LFU五种实现方式,从简单到复杂
- LFU 五种实现方式,从简单到复杂
- 从简单二叉树问题重新来看深度优先搜索
- 从简单日志到全链路日志 我们应该怎么打日志
- 从简单的即时聊天来看架构演变by golang
- 记一次筛选重构
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。