You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:43:01