Dart实现List<FAQCategory>嵌套列表按字段值过滤
Dart 实现FAQ列表多字段过滤
基础定义
已有的数据结构如下:
class FAQCategory { late int id; late String title; late List<FAQItem> items; FAQCategory({ required this.id, required this.title, required this.items, }); } class FAQItem { late int id; late String question; late String answer; FAQItem({ required this.id, required this.question, required this.answer, }); }
过滤规则
- 分类
title匹配查询词:保留该分类下所有条目 - 分类
title未匹配:仅保留question或answer匹配查询词的条目 - 过滤后无有效条目的分类直接移除
现有逻辑缺陷
你目前的实现仅判断了条目question字段的匹配情况,缺失三个核心逻辑:
- 未校验分类
title的匹配规则 - 未覆盖条目
answer字段的匹配判断 - 未对分类下的条目做二次过滤,会返回分类下所有未匹配的冗余条目
可直接运行的实现
版本1:允许修改原列表对象(性能更优)
默认做大小写不敏感匹配,不需要的话删除所有.toLowerCase()调用即可:
List<FAQCategory> filterFAQs(List<FAQCategory> source, String keyword) { if (keyword.trim().isEmpty) return source; final lowerKeyword = keyword.toLowerCase(); return source.where((category) { // 分类标题命中,直接保留全部分类内容 if (category.title.toLowerCase().contains(lowerKeyword)) { return true; } // 标题未命中,过滤分类下的条目 category.items = category.items.where((item) { return item.question.toLowerCase().contains(lowerKeyword) || item.answer.toLowerCase().contains(lowerKeyword); }).toList(); // 过滤后存在有效条目则保留分类 return category.items.isNotEmpty; }).toList(); }
版本2:不修改原数据(无副作用)
如果需要保留原始分类列表不被改动,用这个版本,所有返回对象都是新拷贝的实例:
List<FAQCategory> filterFAQs(List<FAQCategory> source, String keyword) { if (keyword.trim().isEmpty) return List.of(source); final lowerKeyword = keyword.toLowerCase(); final List<FAQCategory> result = []; for (final category in source) { // 分类标题命中,拷贝全部分类内容加入结果 if (category.title.toLowerCase().contains(lowerKeyword)) { result.add(FAQCategory( id: category.id, title: category.title, items: List.of(category.items), )); continue; } // 过滤当前分类下匹配的条目 final matchedItems = category.items.where((item) { return item.question.toLowerCase().contains(lowerKeyword) || item.answer.toLowerCase().contains(lowerKeyword); }).toList(); // 存在匹配条目时,新建分类对象加入结果 if (matchedItems.isNotEmpty) { result.add(FAQCategory( id: category.id, title: category.title, items: matchedItems, )); } } return result; }
调用示例
// 传入原始分类列表和查询词即可得到过滤结果 final filteredResult = filterFAQs(_categories, "查询关键词");
内容的提问来源于stack exchange,提问作者Heikkisorsa
相关产品推荐
相关产品推荐

