首页 > 解决方案 > 如何在 Swift 中将 [AnyObject] 数组转换为 [Hashable] 或 [AnyHashable] 数组?

问题描述

我有一个 AnyObjects ( [AnyObject]) 数组。我知道其中大部分是Hashable. 我如何将这个 AnyObject“转换”为 Hashable/AnyHashable?AnyHashable 只接受一个 Hashable 对象作为参数。

标签: iosswift

解决方案


要将一个对象转换为另一个对象,请使用as. 但是无法自动转换的对象(这是您的情况)您需要使用as?as!。所以最简单的方法:

let hashableArray: [AnyHashable] = array as! [AnyHashable] // Will crash if even one object is not convertible to AnyHashable
let hashableArray: [AnyHashable]? = array as? [AnyHashable] // Will return nil if even one object is not convertible to AnyHashable 

所以一个可能会崩溃,而另一个会产生一个可选数组。

既然你写了“我知道其中大部分是Hashable”,我会说这些都不行。您需要对每个对象进行转换并决定如何处理其余部分。最基本的方法是:

func separateHashable(inputArray: [AnyObject]) -> (hashable: [AnyHashable], nonHashable: [AnyObject]) {
    var hashableArray: [AnyHashable] = [AnyHashable]()
    var nonHashableArray: [AnyObject] = [AnyObject]()
    inputArray.forEach { item in
        if let hashable = item as? AnyHashable {
            hashableArray.append(item)
        } else {
            nonHashableArray.append(item)
        }
    }
    return (hashableArray, nonHashableArray)
}

因此,此方法将转换您的数组并将其拆分为两个数组。然后你可以简单地做let hashableArray: [AnyHashable] = separateHashable(inputArray: array).hashable.

但是,如果您只想提取那些可散列的项目,您可以在数组上使用便捷方法compactMap

let hashableArray: [AnyHashable] = array.compactMap { $0 as? AnyHashable }

但总的来说,这一切都非常危险。这也是为什么您不能简单地将其转换为Hashable. 其原因是 2 个项目可能都是可散列的,但属于不同的类别。然后这两个项目可能会产生相同的哈希,即使它们不代表同一个项目。想象一下有 2 个类:

struct Question: Hashable {
    let id: String
    var hashValue: Int { return id.hashValue }

}

struct Answer: Hashable {
    let id: String
    var hashValue: Int { return id.hashValue }
}

现在,如果我创建一个这样的数组:

let array: [AnyObject] = [
    Question(id: "1"),
    Answer(id: "1")
]

这两个项目都会产生相同的哈希值,其中一个可能会覆盖另一个。


推荐阅读