如何在Swift中将[AnyObject]数组转换为[Hashable]或[AnyHashable]数组?

时间:2019-02-22 08:58:46

标签: ios swift

我有一个AnyObjects([AnyObject])数组。我知道其中大多数是Hashable。我如何将这个AnyObject“投射”到Hashable / AnyHashable? AnyHashable仅将Hashable对象作为参数。

1 个答案:

答案 0 :(得分:2)

要将一个对象投射到另一个对象,请使用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")
]

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