Swift中基于questionId对AnswerModel数组去重的更优方案问询
优化Swift数组按
questionId去重的方案 嘿,你的现有实现逻辑是通顺的,但可以从代码简洁性和安全性两个维度来优化,同时利用Swift标准库的API让代码更优雅。下面给你几个更优的方案:
方案一:利用字典自动去重(最简洁)
Swift的Dictionary天然要求key唯一,我们可以把questionId作为字典的key,对应的AnswerModel作为value,这样就能自动完成去重,最后再把字典的values转回数组即可。
保留第一个出现的元素
// 先过滤掉questionId为nil的元素,避免后续解包崩溃 let validAnswers = self.userAnswers.filter { $0.questionId != nil } // 用字典的uniqueKeysWithValues初始化器,自动保留第一个出现的元素 let uniqueDict = Dictionary(uniqueKeysWithValues: validAnswers.map { ($0.questionId!, $0) }) self.userAnswers = Array(uniqueDict.values)
保留最后一个出现的元素
如果你的需求是保留同一questionId最后出现的元素,用reduce(into:)来构建字典,后面的元素会覆盖前面的:
let validAnswers = self.userAnswers.filter { $0.questionId != nil } let uniqueDict = validAnswers.reduce(into: [Int: AnswerModel]()) { dict, answer in dict[answer.questionId!] = answer // 后续元素覆盖之前的,最终保留最后一个 } self.userAnswers = Array(uniqueDict.values)
方案二:改进原有遍历实现(更安全)
你的原代码里用了element.questionId!强制解包,一旦数组里有questionId为nil的元素,就会直接崩溃。我们可以给原逻辑加上安全解包:
var seen = Set<Int>() var unique = [AnswerModel]() for element in self.userAnswers { guard let questionId = element.questionId else { // 这里可以根据需求选择:跳过该元素,或者做其他处理 continue } if !seen.contains(questionId) { unique.append(element) seen.insert(questionId) } } self.userAnswers = unique
方案对比
- 字典方案:代码最简洁,利用标准库API减少重复逻辑,适合大多数场景;
- 改进后的遍历方案:逻辑更直观,适合需要对每个元素做额外自定义处理的场景;
- 两种方案都解决了原代码中强制解包的崩溃风险,这是很重要的优化点。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

