如何从MuscleListObject数组中按Exercise维度实现搜索过滤?
按Exercise维度实现搜索过滤的正确方式
你的思路方向是对的,但现有代码里用全局变量arrSearchedExercise容易导致数据混乱,而且结构体赋值的处理可以更清晰。我帮你调整一下,确保过滤逻辑准确且不影响原数据:
修正后的searchBar(_:textDidChange:)方法
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchText.isEmpty { isSearching = false arrSearchedMuscle = arrExercise // 显示全部数据 } else { isSearching = true let query = searchText let options: String.CompareOptions = [.caseInsensitive, .diacriticInsensitive] arrSearchedMuscle = arrExercise.compactMap { category in // 先检查肌肉组名称是否匹配搜索词 if category.strMuscleName.range(of: query, options: options) != nil { return category // 匹配的话直接返回原肌肉组 } else { // 过滤当前肌肉组下匹配的练习 let filteredExercises = category.arrMuscleExercise.filter { $0.strExerciseName.range(of: query, options: options) != nil } // 如果有匹配的练习,返回只包含这些练习的新肌肉组实例 guard !filteredExercises.isEmpty else { return nil // 没有匹配的练习就过滤掉这个肌肉组 } return MuscleListObject( strMuscleName: category.strMuscleName, arrMuscleExercise: filteredExercises ) } } } self.tblVWExercise.reloadData() }
关键优化点说明
- 避免全局临时变量:把过滤练习的逻辑放在
compactMap的闭包内部,用局部变量filteredExercises存储结果,不会和其他逻辑产生数据冲突 - 结构体实例化更清晰:因为
MuscleListObject是值类型,直接构造新实例来存储过滤后的练习,不会意外修改原数组里的数据 - 增强匹配兼容性:加上
.diacriticInsensitive选项,能忽略重音符号(比如用户搜"abdominal"和"abdominál"都能匹配) - 逻辑更严谨:用
guard语句判断是否有匹配的练习,代码可读性更高
这样修改后,就能同时支持两种搜索场景:
- 搜索肌肉组名称,返回整个肌肉组
- 搜索练习名称,返回包含该练习的肌肉组(且只保留匹配的练习)
内容的提问来源于stack exchange,提问作者Kuldeep
相关产品推荐
相关产品推荐

