如何用Lodash链式调用或原生JS过滤含动态年份键的对象数组?
问题需求
根据过滤条件filterUpdate,对含动态年份键的对象filteredOwnership进行过滤,得到目标结果filterData。
现有数据
过滤条件对象
var filterUpdate = { assetClass: [{id: 1, name: 'photo'}, {id: 2, name: 'thumbnail'} ], vehicleType: [{id: 1, name: 'nissan'}] }
待过滤的状态数据(年份键动态可变)
this.state.filteredOwnership = { 2020: [], 2021: [{assetClass: 'thumbnail', vehicleType: 'Toyota' }, {assetClass: 'Abs', vehicleType: 'Prius' }], 2022: [{assetClass: 'thumbnail', vehicleType: 'Toyota' }, {assetClass: 'photo', vehicleType: 'Prius' }, {assetClass: 'Abs', vehicleType: 'nissan'}, {assetClass: 'LMO', vehicleType: 'Tesla'} ] }
目标过滤结果
filterData = { 2020: [], 2021: [{assetClass: 'thumbnail', vehicleType: 'Toyota' }], 2022: [{assetClass: 'thumbnail', vehicleType: 'Toyota' }, {assetClass: 'photo', vehicleType: 'Prius' }, {assetClass: 'Abs', vehicleType: 'nissan' } ] }
解决方法
方案一:原生JavaScript实现
先将过滤条件转换为便于匹配的集合,再遍历每个年份的数组完成过滤:
// 预处理过滤条件,提取各字段的目标值集合 const filterValues = { assetClass: new Set(filterUpdate.assetClass.map(item => item.name)), vehicleType: new Set(filterUpdate.vehicleType.map(item => item.name)) }; // 遍历待过滤对象,处理每个年份的数组 const filterData = Object.fromEntries( Object.entries(this.state.filteredOwnership).map(([year, items]) => { const filteredItems = items.filter(item => { // assetClass有过滤条件时校验,无则直接通过 const assetMatch = filterValues.assetClass.size === 0 ? true : filterValues.assetClass.has(item.assetClass); // vehicleType有过滤条件时校验,无则直接通过 const vehicleMatch = filterValues.vehicleType.size === 0 ? true : filterValues.vehicleType.has(item.vehicleType); return assetMatch && vehicleMatch; }); return [year, filteredItems]; }) );
方案二:Lodash链式调用实现
结合Lodash的mapValues、filter、every等方法实现:
const _ = require('lodash'); // 预处理过滤条件,转为字段名到目标值数组的映射 const filterMap = _.mapValues(filterUpdate, items => _.map(items, 'name')); const filterData = _.chain(this.state.filteredOwnership) .mapValues(items => { return _.filter(items, item => { return _.every(filterMap, (allowedValues, key) => { // 过滤条件为空时直接通过,否则检查当前项值是否在允许列表中 return _.isEmpty(allowedValues) || _.includes(allowedValues, item[key]); }); }); }) .value();
内容的提问来源于stack exchange,提问作者Jupiter
相关产品推荐
相关产品推荐

