new Set 过滤数据实战
在表格过滤、多选筛选等场景中如何高效地处理层级数据本文通过一个真实的产品分组过滤案例详解Set数据结构在数据筛选中的妙用并给出健壮性、性能优化方案一、背景与需求在后台管理系统中我们经常遇到这样的表格过滤需求表格每一行数据关联一个group_id产品分组 ID。用户可以通过下拉筛选器选择若干个分组父级。过滤结果需要同时包含所选分组本身及其所有子分组子孙后代下的数据行。也就是说选择“电子产品”分组时不仅要显示group_id等于“电子产品”的行还要显示其子分组如“手机”、“电脑”下的所有行。实现这样一个过滤逻辑既要求代码清晰又要兼顾性能和健壮性。二、传统实现方式的问题初版代码可能这样写filterMethod: ({ option, row }) { const selectedIds option.data; // 假设是数组 if (!selectedIds || selectedIds.length 0) return true; // 遍历每个选中的分组检查当前行是否属于该分组或其子分组 return selectedIds.some(id { const group groupOptions.find(g g.id id); if (!group) return false; return group.id row.group_id || (group.children_id group.children_id.includes(row.group_id)); }); }这种写法虽然直观但存在几个痛点重复查找每次过滤都要遍历selectedIds对每个 ID 还要在groupOptions中查找时间复杂度高O(n*m)。层级局限只支持一层子分组若存在孙级分组则无法匹配。数据安全未对option.data做类型校验可能因数据格式异常导致报错。三、Set登场化繁为简JavaScript 的Set对象提供了 O(1) 的查找性能并且天然去重。我们可以利用Set存储所有需要保留的分组 ID包括选中分组及其后代然后只需判断当前行的group_id是否存在于该集合中一步到位。优化后的代码如下实际案例filterMethod: ({ option, row }) { // 1. 获取筛选数据并进行安全处理 const rawData option.data; if (!rawData || !Array.isArray(rawData) || rawData.length 0) { return true; // 无筛选条件显示全部 } // 2. 将选中的 ID 放入 Set以便快速查找 const selectedSet new Set(rawData); // 3. 获取全部分组数据外部响应式数据 const allGroups groupOptions.value || []; // 4. 递归收集所有需要保留的分组 ID包含后代 const keepIds new Set(); const collect (id) { if (keepIds.has(id)) return; // 防止重复递归 const group allGroups.find(g g.id id); if (!group) return; keepIds.add(group.id); if (Array.isArray(group.children_id)) { group.children_id.forEach(childId collect(childId)); } }; // 对每个选中的 ID 执行收集 rawData.forEach(id collect(id)); // 5. 判断当前行的 group_id 是否在 keepIds 中 return keepIds.has(row.group_id); }四、代码逐段解析1. 筛选数据安全获取const rawData option.data; if (!rawData || !Array.isArray(rawData) || rawData.length 0) return true;明确要求rawData为数组否则视为“未选择任何条件”显示所有行。避免因option.data为字符串或对象时调用new Set()引发异常。2. 使用Set存储选中 IDconst selectedSet new Set(rawData);虽然本例中并未直接使用selectedSet因为我们使用了rawData.forEach循环但若后续需要快速判断某个 ID 是否被选中Set比数组的includes更高效。实际我们直接遍历rawData即可但建立Set是一个好习惯。3. 递归收集后代 IDconst keepIds new Set(); const collect (id) { if (keepIds.has(id)) return; const group allGroups.find(g g.id id); if (!group) return; keepIds.add(group.id); if (Array.isArray(group.children_id)) { group.children_id.forEach(childId collect(childId)); } };核心逻辑从每个选中的分组 ID 出发递归遍历其children_id将所有子孙 ID 加入keepIds。利用Set自动去重避免重复添加且has()检查可提前终止递归防止循环引用。递归深度取决于分组层级若层级过深可考虑改为迭代栈但一般情况下足够。4. 最终匹配return keepIds.has(row.group_id);只需一次Set查找时间复杂度 O(1)比多层循环快得多。五、性能与健壮性优化建议5.1 预构建分组映射表每次过滤都执行allGroups.find查找若分组数量庞大成千上万可提前构建一个Map以id为键const groupMap new Map(); groupOptions.value.forEach(g groupMap.set(g.id, g)); // 在 collect 中改为 const group groupMap.get(id);5.2 缓存过滤结果如果表格数据不常变动可以在筛选条件变化时预先计算好keepIds然后对每一行直接判断减少重复计算。5.3 处理深层级与循环引用如果分组存在循环引用A 的 children 包含 BB 的 children 包含 A上述递归会无限执行。通过keepIds.has(id)检查可以打破循环因为第二次遇到相同 ID 时会直接返回。5.4 明确数据结构在实际业务中应确保groupOptions中的每个对象都有id和children_id字段children_id可以是空数组。使用 TypeScript 或 JSDoc 进行类型注解提升代码可维护性。六、总结Set是处理集合运算的利器去重、判存、交集差集都极为高效特别适合过滤、权限校验等场景。递归展开层级结构通过Set记忆已处理节点既能完整覆盖所有后代又能避免死循环。健壮性不可忽视对输入数据做类型和空值检查能大幅降低生产环境报错概率。性能优化分层对于高频操作预先建立索引Map/Set可显著提升响应速度。通过这个实战案例我们不仅学会了如何用Set优雅地解决复杂过滤问题还掌握了递归、缓存等通用优化手段。在你的下一个表格或树形筛选需求中不妨试试这套组合拳吧附录完整组件化示例Vue 3 Element Plus 风格script setup import { ref } from vue; const groupOptions ref([ { id: g1, name: 电子产品, children_id: [g2, g3] }, { id: g2, name: 手机, children_id: [g4] }, { id: g3, name: 电脑, children_id: [] }, { id: g4, name: 智能手机, children_id: [] }, ]); const tableData ref([ { group_id: g1, product: 电视 }, { group_id: g4, product: iPhone }, { group_id: g3, product: MacBook }, ]); const filterMethod ({ option, row }) { // ... 上述实现 }; /script希望这篇文章能帮助你更好地理解Set在实际开发中的应用并写出更高效、更健壮的过滤逻辑。如有疑问欢迎交流探讨

相关新闻

职场人如何提升猎头关注度:5层过滤机制与实战策略

职场人如何提升猎头关注度:5层过滤机制与实战策略

1. 为什么猎头不来找你?职场人必须知道的5个真相最近和几位资深猎头朋友吃饭,聊到一个有趣的现象:有些能力不错的候选人,工作五六年却从没接到过猎头电话;而有些资历平平的同行,反而经常被猎头"骚扰&q…

2026/7/19 7:05:50阅读更多 →
JavaScript this 绑定规则详解

JavaScript this 绑定规则详解

目录前言五条绑定规则1. 默认绑定(独立调用)2. 隐式绑定(方法调用)3. 显式绑定(call / apply / bind)4. new 绑定(构造函数)5. 箐头函数(词法绑定)优先级排序…

2026/7/19 7:05:50阅读更多 →
从零开始的C语言

从零开始的C语言

自我介绍我是澳门大学ECE的准大一学生,此前完全没有接触过代码、开发等相关知识,属于零基础阶段,专业是电气与电脑工程,会大量用到C语言、硬件编程,因此决定从零开始系统学习编程。这个博客将记录我的学习过程&#xf…

2026/7/19 7:05:50阅读更多 →
如何快速配置Harvester超融合基础设施:面向新手的终极网络管理指南

如何快速配置Harvester超融合基础设施:面向新手的终极网络管理指南

如何快速配置Harvester超融合基础设施:面向新手的终极网络管理指南 【免费下载链接】harvester Open source hyperconverged infrastructure (HCI) software 项目地址: https://gitcode.com/gh_mirrors/ha/harvester 想要轻松构建企业级虚拟化环境却担心复杂…

2026/7/19 11:34:23阅读更多 →
深入解析AM64x/AM243x DDR16SS VBUSM2AXI桥接器配置与优化

深入解析AM64x/AM243x DDR16SS VBUSM2AXI桥接器配置与优化

1. 项目概述与核心价值 在嵌入式系统,尤其是像TI AM64x/AM243x这类多核异构处理器的开发中,内存子系统的性能与稳定性往往是决定整个系统成败的关键。很多工程师在拿到芯片和SDK后,能够快速搭建起一个“能跑”的系统,但一旦涉及到…

2026/7/19 11:34:23阅读更多 →
深入解析DMA传输请求与缓冲区描述符:嵌入式系统数据搬运的核心机制

深入解析DMA传输请求与缓冲区描述符:嵌入式系统数据搬运的核心机制

1. 项目概述在嵌入式系统开发,尤其是涉及高速数据流处理的领域,直接内存访问(DMA)技术是性能优化的核心。它让数据搬运这件“苦力活”从CPU肩上卸下,交给专门的硬件引擎去完成,从而让CPU能专注于计算和决策…

2026/7/19 11:34:23阅读更多 →
Cursor破解工具终极指南:如何绕过试用限制实现永久免费使用

Cursor破解工具终极指南:如何绕过试用限制实现永久免费使用

Cursor破解工具终极指南:如何绕过试用限制实现永久免费使用 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached you…

2026/7/19 11:34:23阅读更多 →
终极Windows PS3手柄兼容驱动:DsHidMini完整使用指南

终极Windows PS3手柄兼容驱动:DsHidMini完整使用指南

终极Windows PS3手柄兼容驱动:DsHidMini完整使用指南 【免费下载链接】DsHidMini Virtual HID Mini-user-mode-driver for Sony DualShock 3 Controllers 项目地址: https://gitcode.com/gh_mirrors/ds/DsHidMini 还在为Windows系统无法识别你的PlayStation …

2026/7/19 11:34:23阅读更多 →
LGTV Companion终极指南:如何让OLED电视与Windows电脑智能联动

LGTV Companion终极指南:如何让OLED电视与Windows电脑智能联动

LGTV Companion终极指南:如何让OLED电视与Windows电脑智能联动 【免费下载链接】LGTVCompanion Power On and Off WebOS LG TVs together with your PC 项目地址: https://gitcode.com/gh_mirrors/lg/LGTVCompanion LGTV Companion是一款专门解决OLED电视与W…

2026/7/19 11:32:23阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/18 22:49:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →