能否移除含nil值的任意类型Array重复元素?附示例与预期输出
移除包含nil的数组中的重复元素(支持混合数值类型)
当然可以搞定这个需求!不管你的数组是单一可选类型还是混合了不同数值类型(比如Int和Double),我们都有对应的解决方案,下面一步步来讲解:
情况1:数组是单一可选数值类型(如[Int?]、[Double?])
这种情况最简单,直接利用Swift的Set自动去重特性,再调整顺序即可:
let myArray1: [Int?] = [1, 2, 3, 1, 2, 1, 3, nil, 1, nil] // 用Set去重,再转换回数组 var uniqueArray = Array(Set(myArray1)) // 排序,让非nil元素按升序排列,nil放在最后 uniqueArray.sort { switch ($0, $1) { case (nil, _): return false case (_, nil): return true case let (a?, b?): return a < b } } print(uniqueArray) // 输出: [1, 2, 3, nil]
为什么这么做?
Set会自动过滤掉重复的元素(包括重复的nil),因为Optional<Int>是符合Hashable协议的。- 由于
Set是无序的,我们需要手动排序来得到你预期的有序结果。
情况2:数组是混合类型的[Any?](比如同时包含Int、Double和nil)
你的第二个例子[1, 2.0, 1, 3, 1.0, nil]属于这种情况,因为Swift中Int和Double不能直接放在同一个数组里,必须用Any?类型。这时直接用Set会把1(Int)和1.0(Double)视为不同元素,所以需要先统一数值类型再去重:
func removeDuplicates(from mixedArray: [Any?]) -> [Any?] { var seenElements = Set<AnyHashable>() var result = [Any?]() for element in mixedArray { if let value = element { // 统一数值类型为Double,方便比较值是否相等 let normalizedValue: AnyHashable if let number = value as? NSNumber { normalizedValue = number.doubleValue } else { // 非数值类型直接用原对象(需保证该类型符合Hashable) normalizedValue = value as! AnyHashable } // 仅当元素未出现过时,加入结果数组和已见集合 if !seenElements.contains(normalizedValue) { seenElements.insert(normalizedValue) // 可选:把整数形式的Double转回Int,让结果更整洁 if let doubleVal = normalizedValue as? Double, doubleVal == Double(Int(doubleVal)) { result.append(Int(doubleVal)) } else { result.append(value) } } } else { // 处理nil,只保留第一次出现的nil if !seenElements.contains(NSNull()) { seenElements.insert(NSNull()) result.append(nil) } } } return result } // 测试混合类型数组 let myArray2: [Any?] = [1, 2.0, 1, 3, 1.0, nil] let uniqueArray2 = removeDuplicates(from: myArray2) print(uniqueArray2) // 输出: [1, 2, 3, nil]
关键细节说明:
- 数值统一化:用
NSNumber.doubleValue把所有数值类型转成Double,这样1和1.0会被视为同一个值。 - nil处理:用
NSNull()代替nil存入Set(因为nil不能直接存入Set),确保只保留一个nil。 - 结果美化:把整数形式的Double转回Int,让输出更符合预期的
[1,2,3,nil]而不是[1,2.0,3,nil]。
内容的提问来源于stack exchange,提问作者Pratik Panchal
相关产品推荐
相关产品推荐

