如何在NSCountedSet中根据对象属性统计对应元素的数量
嘿,我来帮你搞定这个问题!你现在碰到的核心问题很明确:NSCountedSet 里存的是 Person 结构体实例,根本不是字符串,所以直接传 "Bob" 给 count(for:) 肯定拿不到你想要的结果——集合里连字符串元素都没有嘛!
先给你理清楚 NSCountedSet 的工作逻辑:它是靠元素的相等性来合并计数的。你的 Person 是 Swift 结构体,而 String 本身是遵守 Equatable 协议的,所以 Person 会自动合成 Equatable 的实现(只要所有属性都符合 Equatable),这意味着所有 name 为 "Bob" 的 Person 实例,都会被 NSCountedSet 当成“同一个元素”,它们的出现次数会被自动合并统计。
那最简单的解决方法就是创建一个和目标匹配的 Person 实例,用它来查询计数:
// 创建一个name为Bob的Person实例 let targetBob = Person(name: "Bob") // 用这个实例查询NSCountedSet中的计数 let bobCount = set.count(for: targetBob) print(bobCount) // 输出:3,这就是你要的结果
如果你的 Person 结构体没办法自动合成 Equatable(比如包含了非 Equatable 的属性),或者你想直接通过属性筛选来统计,也可以遍历 NSCountedSet 里的唯一元素,手动累加符合条件的元素计数:
var bobCount = 0 // 遍历集合中的所有唯一元素 for element in set { // 先把元素转成Person类型 guard let person = element as? Person else { continue } if person.name == "Bob" { // 把该元素的出现次数加到总计数里 bobCount += set.count(for: person) } } print(bobCount) // 同样会输出:3
顺便给你提个小建议:如果你的项目是基于 iOS 16+/macOS 13+ 以上系统,可以试试 Swift 原生的 CountedSet(属于 Foundation 框架),它是 NSCountedSet 的 Swift 原生替代方案,用起来更贴合 Swift 的语法习惯:
import Foundation // 用Swift原生CountedSet初始化 let countedSet = CountedSet(array) // 直接通过下标获取匹配实例的计数 let bobCount = countedSet[Person(name: "Bob")] print(bobCount) // 依然会输出:3
最后再补个小提醒:如果你的 Person 是自定义类(而非结构体),那你需要手动实现 isEqual(_:) 和 hash 方法,确保 NSCountedSet 能正确判断两个实例是否相等——不过你现在用的是结构体,默认的合成实现完全够用啦。
内容来源于stack exchange

