如何在UISearchController中过滤分组后的Dictionary<String, [People]>内的数组?
解决UISearchController中过滤分组字典的问题
你目前的过滤代码只检查了每个分组里是否存在符合搜索条件的元素,只要有一个匹配,就会保留整个分组的所有元素——这就是为什么"A"分组里的Ahmet也被留下来了。要实现「同时过滤分组和分组内元素」的效果,我们需要两步操作:先过滤每个分组内的匹配元素,再移除过滤后为空的分组。
正确的过滤实现
这里推荐用reduce(into:)来高效构建过滤后的字典,代码如下:
// 假设你的搜索词是这个,实际可以从UISearchBar获取 let searchText = "ata".lowercased() let filteredDict = dict.reduce(into: [String: [People]]()) { result, entry in // 第一步:过滤当前分组中符合条件的People对象 let matchedPeople = entry.value.filter { person in person.name.lowercased().contains(searchText) } // 第二步:只有当分组过滤后还有元素时,才加入结果字典 if !matchedPeople.isEmpty { result[entry.key] = matchedPeople } }
代码解释
reduce(into:)的作用:它会帮我们从零开始构建一个新字典,避免先过滤再额外处理空分组的麻烦。- 分组内元素过滤:对每个分组(
entry),用filter筛选出名字包含搜索词的Person对象(统一转小写是为了实现大小写不敏感的搜索)。 - 移除空分组:如果某个分组过滤后没有匹配的元素,就不把它加入结果字典,这样最终的字典里只会包含有匹配项的分组,且每个分组里只有符合条件的元素。
集成到UISearchController的示例
如果要把这个逻辑放到UISearchController的搜索更新方法里,可以这样写:
func updateSearchResults(for searchController: UISearchController) { guard let inputText = searchController.searchBar.text?.lowercased(), !inputText.isEmpty else { // 搜索框为空时,恢复原始字典 self.filteredDict = self.dict self.tableView.reloadData() return } // 执行过滤逻辑 self.filteredDict = self.dict.reduce(into: [String: [People]]()) { result, entry in let matched = entry.value.filter { $0.name.lowercased().contains(inputText) } if !matched.isEmpty { result[entry.key] = matched } } self.tableView.reloadData() }
这样就能实现用户输入时,表格视图实时展示过滤后的分组和元素啦~
内容的提问来源于stack exchange,提问作者atalayasa
相关产品推荐
相关产品推荐

