user3574603
user3574603

Reputation: 3618

Swift 5.1: How do I call map on a collection of one type and return another of a different type?

I've been playing about with functional programming in Swift. However, I've encountered a problem.

If I call map on a collection of one type, how do I create a new collection of another type?

var fontFamilyMembers = [[Any]]()

//...
let postscriptNames = fontFamilyMembers.map {
    [
        "name": $0[0] as! String,
        "weight": $0[2] as! Int,
        "traits": $0[3] as! UInt
    ]
}

// Error: Value of type 'Any?' has no member 'count'
lengths = postscriptNames.map { $0["name"].count }

I understand I need to cast $0["name"] as a string. Why do I have to do that when I have already done it above? ("name": $0[0] as! String). Is that because postscriptNames is also type [[Any]]()?

I've tried this:

// Error: Cannot convert value of type 'Int' to closure result type 'String'
fontPostscriptNames = postscriptNames.map { ($0["name"] as! String).count }.joined(separator: "\n")

…but know I'm doubly confused.

How do I get map to return the count of each "name"?

Update

My original question still stands. However, I can avoid the problem altogether by using a struct as opposed to a dictionary which I assume is preferred in Swift.

        let postscriptNames = fontFamilyMembers.map {
            (
                name: $0[0] as! String,
                weight: $0[2] as! Int,
                traits: $0[3] as! UInt
            )
        }

        lengths = postscriptNames.map { $0.name.count }

Upvotes: 0

Views: 703

Answers (1)

mutAnT
mutAnT

Reputation: 464

Is that because postscriptNames is also type [Any]?

Yes. And as postscriptNames is of type [Any], you need to downcast $0.name to String

lengths = postscriptNames.compactMap { ($0.name as? String).count }

Downcast it to String to get the count.

Upvotes: 2

Related Questions