简体   繁体   中英

How can I cast an array of [AnyObject] to an array of [Hashable] or [AnyHashable] in Swift?

I have an array of AnyObjects ( [AnyObject] ). I know most of these are Hashable . How would I "cast" this AnyObject to a Hashable/AnyHashable? AnyHashable only takes a Hashable object as a parameter.

To cast one object to another you use as . But the objects that can not be automatically converted (which is your case) you need to use either as? or as! . So the most simple way:

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 

So one may crash while the other one will produce an optional array.

Since you wrote "I know most of these are Hashable " I would say that none of these are OK. You need to do the transform per-object and decide what to do with the rest. The most basic approach is:

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)
}

So this method will convert your array and split it into two arrays. You could then simply do let hashableArray: [AnyHashable] = separateHashable(inputArray: array).hashable .

But if you want to only extract those items that are hashable you can use convenience method on array compactMap

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

But in general this all very dangerous. And also that is why you can't simply convert it to Hashable . The reason for it is that 2 items may both be hashable but are of different class. And then both of the items may produce same hash even though they do not represent the same item. Imagine having 2 classes:

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

}

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

Now if I create an array like this:

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

both of the items would produce the same hash and one would potentially overwrite the other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM