Swift 5中如何过滤包含嵌套字典的字典?
如何过滤嵌套字典并将匹配值存入filteredData?
首先,咱们先看看你代码里的问题:你把字典Data转成NSArray然后过滤,最后还试图转成[String],这肯定不对——因为你的原数据是[Int : [String : String]]类型,转成数组会丢失原字典的key信息,而且类型转换完全不匹配,运行时肯定会崩溃。
针对嵌套字典的过滤,咱们用Swift原生的API就能轻松搞定,不用绕到NSPredicate(当然也能用,但原生方法更直观)。下面分两种场景给你方案:
场景1:搜索嵌套字典中任意值是否包含关键词
如果只要嵌套字典里的任意一个值包含搜索文本(忽略大小写),就保留这个条目,可以这么写:
// 先安全获取搜索文本,避免强制解包崩溃 guard let searchText = searchController.searchBar.text?.lowercased(), !searchText.isEmpty else { filteredData = Data // 搜索文本为空时返回全部数据 return } // 过滤字典:保留那些嵌套字典中至少有一个值包含搜索文本的条目 filteredData = Data.filter { _, valueDict in valueDict.values.contains { $0.lowercased().contains(searchText) } }
代码解释:
Data.filter会遍历字典的每一组键值对(key和对应的嵌套字典valueDict)valueDict.values.contains检查嵌套字典的所有值中,是否存在任意一个字符串转小写后包含搜索文本(转小写是为了实现忽略大小写的匹配,对应你原来的[c]选项)
场景2:只搜索嵌套字典中特定key对应的值
如果你只想匹配嵌套字典里某个特定key(比如只搜"username"对应的值),可以修改过滤条件:
guard let searchText = searchController.searchBar.text?.lowercased(), !searchText.isEmpty else { filteredData = Data return } filteredData = Data.filter { _, valueDict in // 只检查嵌套字典中"username"这个key对应的值 if let targetValue = valueDict["username"]?.lowercased() { return targetValue.contains(searchText) } return false }
如果你一定要用NSPredicate
如果习惯用NSPredicate,也可以这么实现(同样以搜索任意值为例):
guard let searchText = searchController.searchBar.text else { filteredData = Data return } let predicate = NSPredicate(format: "ANY values CONTAINS[c] %@", searchText) filteredData = Data.filter { predicate.evaluate(with: $0.value) }
最后提醒:
尽量避免用!强制解包searchController.searchBar.text,万一文本为空会直接崩溃,用guard let或者if let做安全解包更稳妥。
内容的提问来源于stack exchange,提问作者GoForIt
相关产品推荐
相关产品推荐

