如何检测NSMutableArray中的重复值(含空字符串场景)
解决数组重复值统计的问题
看起来你当前的代码统计的是出现次数≥2的元素种类数,但在空字符串重复的场景下,这个结果不符合你的预期——我猜你想要的是统计数组中所有重复元素的总个数(也就是非首次出现的元素数量),或者更清晰地说,是总元素数减去唯一元素的数量?
先梳理下问题:你的原代码用NSCountedSet统计的是「有多少种元素重复出现了」,比如在["a.a@gmail.com", "", "", "b.b@gmail.com", "", ""]这个数组里,只有空字符串是重复的,所以返回1。但如果你的需求是统计「总共有多少个元素是重复的实例」(比如这里空字符串出现4次,其中3个是重复的,总重复数是3),那原代码就不适用了。
下面给你几种不同需求下的实现方案,都是用Swift原生语法,比Objective-C的API更简洁直观:
方案1:统计所有重复元素的总个数(非首次出现的元素数量)
这应该是你需要的场景,计算方式是「数组总长度 - 唯一元素的数量」:
// 先把NSMutableArray转成Swift原生的[String]数组,避免类型转换麻烦 let arrEmails = NSMutableArray(array: ["a.a@gmail.com", "", "", "b.b@gmail.com", "", ""]) let swiftEmails = arrEmails as! [String] let uniqueEmails = Set(swiftEmails) let totalDuplicateInstances = swiftEmails.count - uniqueEmails.count print(totalDuplicateInstances) // 输出3,符合你的预期
方案2:统计有多少种元素是重复出现的(原代码逻辑优化版)
如果你只是想优化原代码的写法,用Swift原生的字典统计频率会更清晰:
let arrEmails = NSMutableArray(array: ["a.a@gmail.com", "a.a1@gmail.com", "a.a@gmail.com", "b.b@gmail.com", "c.c@gmail.com", "a.a1@gmail.com"]) let swiftEmails = arrEmails as! [String] // 统计每个元素的出现频率 var frequencyMap: [String: Int] = [:] for email in swiftEmails { frequencyMap[email, default: 0] += 1 } // 筛选出出现次数≥2的元素,统计种类数 let duplicateTypesCount = frequencyMap.filter { $0.value >= 2 }.count print(duplicateTypesCount) // 输出2,和原代码结果一致,但写法更简洁
方案3:统计每个重复元素的重复次数明细
如果需要更细致的统计,可以计算每个元素的「出现次数-1」的总和:
let arrEmails = NSMutableArray(array: ["a.a@gmail.com", "", "", "b.b@gmail.com", "", ""]) let swiftEmails = arrEmails as! [String] var frequencyMap: [String: Int] = [:] for email in swiftEmails { frequencyMap[email, default: 0] += 1 } let totalDuplicateCounts = frequencyMap.reduce(0) { result, entry in result + max(entry.value - 1, 0) } print(totalDuplicateCounts) // 输出3,和方案1结果一致,但能看到每个元素的重复明细
另外,建议尽量使用Swift原生的Array而不是NSMutableArray,类型更安全,API也更贴合Swift的编程习惯。
内容的提问来源于stack exchange,提问作者Pankil
相关产品推荐
相关产品推荐

