JavaScript根据指定数组筛选含数组成员对象的方法
嵌套分类数据过滤实现问题
场景与需求
从接口获取到按类别分组的动物数据,结构如下:
const animals = { bugs: ['ant', 'cricket'], fish: ['shark', 'whale', 'tuna'], mammals: ['cow', 'horse', 'sheep'], birds: ['eagle', 'crow', 'parrot'], predators: ['tiger', 'lion'] }
需要使用如下白名单数组对数据做过滤,仅保留白名单内存在的物种,同时保留原有的分类结构,无匹配物种的分类直接剔除:
const data = ['shark', 'horse', 'cow', 'parrot']
预期输出结果:
const filtered = { fish: ['shark'], mammals: ['cow', 'horse'], birds: ['parrot'], }
原有代码问题
最初编写的过滤逻辑运行后结果不符合预期,同分类下匹配到多个元素时只会保留最后一个,存在覆盖问题,原代码如下:
filter.forEach((item) => { for (let key in animals) { let species = [] if (animals[key].includes(item)) { filtered[key] = [...species, species] } } })
注:原代码中遍历的
filter为变量笔误,实际应为过滤使用的白名单数组data。
错误运行结果:
const filtered = { fish: ['whale'], mammals: ['cow',], birds: ['parrot'], }
核心问题点:
- 每次循环内部都重新声明空数组
species,没有存储任何已匹配的元素 - 匹配到元素时直接对
filtered[key]做整体赋值,会直接覆盖该分类下之前已经存入的匹配项 - 展开空数组后拼接空数组的写法逻辑错误,没有把当前匹配到的
item写入结果 - 遍历维度不合理,以白名单元素为遍历维度时,没有做分类结果的初始化判断
修复方案
方案1:按原数据分类维度遍历(推荐)
直接遍历原始数据的所有分类,对每个分类下的物种数组做筛选,仅保留白名单内的元素,筛选后有剩余元素的分类才写入最终结果,从根源上避免元素覆盖问题:
const animals = { bugs: ['ant', 'cricket'], fish: ['shark', 'whale', 'tuna'], mammals: ['cow', 'horse', 'sheep'], birds: ['eagle', 'crow', 'parrot'], predators: ['tiger', 'lion'] } const data = ['shark', 'horse', 'cow', 'parrot'] const filtered = {} for (const category in animals) { // 筛选当前分类下在白名单内的物种 const matchedSpecies = animals[category].filter(species => data.includes(species)) // 仅保留有匹配项的分类 if (matchedSpecies.length) { filtered[category] = matchedSpecies } }
运行后可直接得到和预期完全一致的结果,逻辑更清晰,遍历次数更少。
方案2:修正原有白名单遍历逻辑
如果需要保留原有遍历白名单的写法,只需要补上分类初始化逻辑,匹配到元素时用追加而非整体赋值即可:
const filtered = {} data.forEach((item) => { for (const category in animals) { if (animals[category].includes(item)) { // 分类首次匹配到时初始化为空数组 if (!filtered[category]) { filtered[category] = [] } // 追加当前匹配到的元素,不会覆盖已有内容 filtered[category].push(item) } } })
内容的提问来源于stack exchange,提问作者Skygazer
相关产品推荐
相关产品推荐

