Swift获取数组唯一元素时如何保持原顺序并保证ID与名称对应
解决Swift中去重后数组元素对应关系混乱的问题
这个问题的核心是你把nationalitiesid和nationalities拆成两个独立数组处理,用Set去重时会打乱原有顺序,而且没法保证两个数组的元素对应关系。咱们换个思路,先把国籍ID和名称绑定成一组数据,再对这组数据去重并保留顺序,最后拆分回两个数组就能解决问题。
具体解决方案
第一步:绑定关联数据,避免拆分数组
先把循环里的逻辑改成收集配对的(id, name)元组,而不是分别存入两个数组,这样能始终保证ID和名称的对应关系:
// 先读取一次nationalities数组,避免循环里重复IO操作(优化点) guard let decoded4 = userDefaults.object(forKey: "nationalities") as? Data, let decodedNationalities = NSKeyedUnarchiver.unarchiveObject(with: decoded4) as? [Nationality] else { // 处理解码失败的情况,别用强制解包! return } // 定义数组保存配对的ID和名称 var nationalityPairs = [(id: Int, name: String)]() for shift in filtered_shifts { // 用first(where:)替代内层循环,效率更高 if let matchedNationality = decodedNationalities.first(where: { $0.id == shift.idNationality }) { nationalityPairs.append((id: matchedNationality.id, name: matchedNationality.name)) } }
第二步:去重并保留顺序
这里有两种靠谱的方式,都能保证去重后ID和名称的对应关系,同时保留首次出现的顺序:
方式一:利用有序字典(Swift 4.2+)
Swift 4.2之后的Dictionary会保留插入顺序,我们用ID作为key自动去重,再提取值即可:
// 用ID作为key,自动去重,保留首次出现的配对 let uniquePairDict = Dictionary(nationalityPairs.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first }) // 提取有序的配对数组 let sortedUniquePairs = Array(uniquePairDict.values) // 拆分回目标数组 uniqueNationalityid = sortedUniquePairs.map { $0.id } uniqueNationality = sortedUniquePairs.map { $0.name }
方式二:手动遍历去重(兼容旧版本Swift)
用一个辅助Set记录已经处理过的ID,遍历配对数组时只保留首次出现的元素:
var seenIds = Set<Int>() var uniquePairs = [(id: Int, name: String)]() for pair in nationalityPairs { if !seenIds.contains(pair.id) { seenIds.insert(pair.id) uniquePairs.append(pair) } } // 拆分回目标数组 uniqueNationalityid = uniquePairs.map { $0.id } uniqueNationality = uniquePairs.map { $0.name }
为什么原来的方法会出错?
Set是无序集合,转换回数组时的元素顺序是不确定的,所以两个独立数组去重后,uniqueNationalityid和uniqueNationality的元素对应关系就会混乱。而把ID和名称绑定成一组数据处理,就能始终保证每一组的对应关系,去重后顺序也完全符合预期。
内容的提问来源于stack exchange,提问作者mrs.bassim
相关产品推荐
相关产品推荐

