如何将'Any?'类型转换为带灵活泛型属性的结构体?
处理包含SplitValue结构体的[Any?]数组
我懂你现在的处境:第三方库返回了一个[Any?]类型的数组,里面塞的是你定义的SplitValue结构体实例,而且这个结构体已经实现了Equatable协议。下面我会针对几个常见的使用场景,给出实用的处理方案:
1. 安全转换数组元素类型
原数组是[Any?],直接操作很容易踩类型坑,第一步最好把它转换成明确的[SplitValue<L, R>?]类型(这里的L和R要替换成你实际用的具体类型,比如String、Int)。用compactMap就能同时过滤掉nil并完成类型转换:
// 假设你的SplitValue实际是SplitValue<String, Int>类型 let originalArray: [Any?] = thirdPartyLibraryReturnedArray let convertedArray = originalArray.compactMap { $0 as? SplitValue<String, Int> }
转换后的convertedArray是[SplitValue<String, Int>]类型,后续操作就完全符合类型安全要求了。
2. 判断数组中是否包含某个特定的SplitValue
因为SplitValue已经实现了Equatable,转换类型之后直接用contains方法就行:
let targetValue = SplitValue(left: "test", right: 123) let hasTarget = convertedArray.contains(targetValue)
要是不想提前转换整个数组,也可以直接在原数组里判断,但一定要做好类型检查:
let hasTarget = originalArray.contains { element in guard let splitVal = element as? SplitValue<String, Int> else { return false } return splitVal == targetValue }
3. 对数组中的SplitValue去重
利用Equatable的特性,有两种常见的去重方式:
- 方式一:借助Set去重(注意:Set要求元素遵循
Hashable,所以需要给SplitValue添加Hashable实现)
extension SplitValue: Hashable where L: Hashable, R: Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(left) hasher.combine(right) } } let uniqueArray = Array(Set(convertedArray))
- 方式二:手动遍历去重(不需要额外实现Hashable,适合不想修改原结构体扩展的场景)
var uniqueArray: [SplitValue<String, Int>] = [] for value in convertedArray { if !uniqueArray.contains(value) { uniqueArray.append(value) } }
4. 关于你的SplitValue的Equatable实现
你写的==方法完全没问题,它会同时比较left和right两个可选属性,完全符合Equatable协议的要求,所以上面所有的比较操作都是可靠的。
内容的提问来源于stack exchange,提问作者Tonnie
相关产品推荐
相关产品推荐

