【问题标题】:Swift: for loop, search dictionary, set variables from keysSwift:for循环,搜索字典,从键设置变量
【发布时间】:2016-06-18 21:23:52
【问题描述】:

错误是:无法转换类型(字符串:Int)的值?到指定类型“字符串”。

显然,我的字典 'roster' 是 'String: Int' 而函数 'printRoster' 中的局部变量('lastPlayer' 和 'firstPlayer')是 String。但是我已经尝试了所有变体,但没有运气。在我制作 roster 字典之前它工作得很好,它只是一个字符串。

它应该做什么:函数连接一个字符串,使其具有正确的标点符号。第一个字符串是“名册包括”,然后我们添加位于字典“名册”键中的每个玩家。但是花名册中的第一个键没有逗号,最后一个键有一个 ', and'。

另外,我可以将字典“名册”添加到协议中吗,在任何 Apple 手册中都没有看到语法

    import UIKit

protocol basketballTeams {
    var teamName: String? { get }
    var numberOfPlayers: Int? { get }
    var locatedIn: String? { get }

    func printTeamLocation()
}

class BasketballTeam {
    var teamName: String?
    var numberOfPlayers: Int?
    var locatedIn: String?
    var roster = [String: Int]()

    init(teamName: String) {
        self.teamName = teamName
    }

    func printTeamLocation() -> String {
        return "The \(teamName) are located in \(locatedIn)"
    }
    func printRoster() -> String {
        var rosterPrint = "The roster includes"
        for player in roster.keys {

            rosterPrint += player

            var firstPlayer: String = roster.first
            var lastPlayer = roster.last

            if (player == firstPlayer) {
                rosterPrint += " \(player)"
            }
            else if (player == lastPlayer) {
                rosterPrint += ", and \(player)."
            }
            else {
            rosterPrint += ", \(player)"
            }
        }
        return rosterPrint
    }
}

enum NumberedPosition: Int {
    case PointGuard = 1
    case ShootingGuard, SmallForward, PowerForward, Center
    func labelOfPosition() -> String {
        switch self {
        case .PointGuard:
            return "Point Guard"
        case .ShootingGuard:
            return "Shooting Guard"
        case .SmallForward:
            return "Small Forward"
        case .PowerForward:
            return "Power Forward"
        case .Center:
            return "Center"
        default:
            "Position doesn't exit"
        }
    }
}

let goldenStateWarriors = BasketballTeam(teamName: "Golden State Warriors")
goldenStateWarriors.numberOfPlayers = 12
goldenStateWarriors.locatedIn = "Oakland, California"
goldenStateWarriors.roster = ["Stephen Curry" : 1, "Andrew Bogut" : 5, "Klay Thompson" : 2]
goldenStateWarriors.roster["Harrison Barnes"] = 3

【问题讨论】:

    标签: swift string dictionary


    【解决方案1】:

    这个怎么样:

    let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
    
    let players = roster.keys.joined(separator: ", ")
    let all = "Roster contains: \(players)."
    

    【讨论】:

    • 比我的解决方案更好,恭喜!但是请注意,在 Swift 2.2 中,正确的语法仍然是 joinWithSeparator
    • 虽然这可行,但它似乎没有我正在寻找的动态。我希望完全正确的语法和 for 循环能够工作,这样我就可以构建更高级的功能。因为我接下来要做的就是将值与枚举器联系起来。
    【解决方案2】:

    如果您仍想在最后一行添加“and”,您可以使用此功能:

    func printRoster() -> String {
      var rosterPrint = "The roster includes"
      let arr = Array(roster.keys)
      let firstPlayer: String = arr.first!
      let lastPlayer: String = arr.last!
      for (player, _ ) in roster {
        switch player {
        case firstPlayer:
          rosterPrint += " \(player)"
        case lastPlayer:
          rosterPrint += ", and \(player)."
        default:
          rosterPrint += ", \(player)"
        }
       }
       return rosterPrint
    }
    

    然后这样称呼它:

    print(goldenStateWarriors.printRoster())
    

    【讨论】:

    • 好的,所以基本上swift不会让我对字典进行操作,我必须将键复制到重复的数组中,然后我可以做到。如果是这种情况,他们有可能在 3.0 中解决这个问题吗?
    • 是的,roster.keys 返回一个LazyMapCollection,它不能用Int 进行索引并且没有last 方法,因此复制到数组允许您使用last方法来设置lastPlayer编辑我认为它不会被修复,仅仅是因为它没有被破坏。 LazyMapCollection 允许更好地访问大型字典。 @JamesGoldstein
    • '.count - 1' 可以在不复制到数组的情况下工作吗?
    • 不幸的是,LazyMapCollections 不能被 Int 值索引,它们使用自己的索引类型。看这里:developer.apple.com/reference/swift/lazymapcollection@JamesGoldstein
    • 太棒了!效果很好
    【解决方案3】:

    鉴于这本词典

    let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
    

    你可以

    let elms = roster
        .keys
        .reduce("") { $0.1 + ", " + $0.0 }
        .characters
        .dropLast()
        .dropLast()
    
    let res = "The roster includes " + String(elms)
    

    结果

    "The roster includes Andrew Bogu, Stephen Curry, Klay Thompson"
    

    更新 #1:使用 FOR 循环

    既然你想使用 for 循环,这里是代码

    let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
    var result = "The roster includes "
    for (index, elm) in roster.keys.enumerate() {
        result += elm
        if index < roster.keys.count - 1 {
            result += ", "
        }
    }
    
    print(result) // The roster includes Klay Thompson, Stephen Curry, Andrew Bogu
    

    更新 #2:将 FOR LOOP 与 first 和 last 一起使用

    let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
    
    func printRoster() -> String {
    
        var rosterPrint = "The roster includes"
        let players = Array(roster.keys)
    
    
        guard let
            first = players.first,
            last = players.last
            else { return "" } // this is ugly, it should return nil instead...
    
        for player in players {
            switch player {
            case first: rosterPrint += " \(player)"
            case last: rosterPrint += ", and \(player)."
            default: rosterPrint += ", \(player)"
            }
        }
        return rosterPrint
    }
    
    printRoster() // "The roster includes Klay Thompson, Stephen Curry, and Andrew Bogu."
    

    【讨论】:

    • 也比我想要的更简单。我希望保留 for 循环。语法也要正确。
    • @JamesGoldstein:我添加了 FOR LOOP 实现
    • 谢谢,但我认为像上面一样使用更新的 Swift 函数 .first 和 .last 可能会更好。
    • 实际上,也许不是。看起来我可以将键复制到数组中并将我的代码与“.last”或“.first”一起使用,或者我可以保存复制步骤并使用“.count - 1”。
    • @JamesGoldstein:刚刚又更新了我的答案,请看一下
    【解决方案4】:

    这似乎运作良好,至少在他们允许 .first 和 .last 使用字典之前(如果可能的话)。

        class BasketballTeam {
        var teamName: String?
        var numberOfPlayers: Int?
        var locatedIn: String?
        var roster = [String: Int]()
    
        init(teamName: String) {
            self.teamName = teamName
        }
    
        func printTeamLocation() -> String {
            return "The \(teamName) are located in \(locatedIn)"
        }
        func printRoster() -> String {
            var rosterPrint = "The roster includes"
            let rosterArray = Array(roster.keys)
    
            for player in rosterArray {
    
                let firstPlayer = rosterArray.first
                let lastPlayer = rosterArray.last
    
                switch player {
                case firstPlayer!:
                    rosterPrint += " \(player)"
                case lastPlayer!:
                    rosterPrint += ", and \(player)."
                default:
                    rosterPrint += ", \(player)"
                }
            }
            return rosterPrint
        }
    }
    

    完整代码,如果您想快速学习并熟悉篮球,可以粘贴到游乐场

    import UIKit
    
    protocol basketballTeams {
        var teamName: String { get }
        var numberOfPlayers: Int { get }
        var locatedIn: String { get }
        var roster: [String: Int] { get }
    
        func printTeamLocation()
    }
    
    class BasketballTeam {
        var teamName: String?
        var numberOfPlayers: Int?
        var locatedIn: String?
        var roster = [String: Int]()
    
        init(teamName: String) {
            self.teamName = teamName
        }
    
        func printTeamLocation() -> String {
            return "The \(teamName) are located in \(locatedIn)"
        }
        func printRoster() -> String {
            var rosterPrint = "The roster includes"
            let rosterArray = Array(roster.keys)
    
            for player in rosterArray {
    
                let firstPlayer = rosterArray.first
                let lastPlayer = rosterArray.last
    
                switch player {
                case firstPlayer!:
                    rosterPrint += " \(player)"
                case lastPlayer!:
                    rosterPrint += ", and \(player)."
                default:
                    rosterPrint += ", \(player)"
                }
            }
            return rosterPrint
        }
    }
    
    enum NumberedPosition: Int {
        case PointGuard = 1
        case ShootingGuard, SmallForward, PowerForward, Center
        func labelOfPosition() -> String {
            switch self {
            case .PointGuard:
                return "Point Guard"
            case .ShootingGuard:
                return "Shooting Guard"
            case .SmallForward:
                return "Small Forward"
            case .PowerForward:
                return "Power Forward"
            case .Center:
                return "Center"
            default:
                "Position doesn't exist"
            }
        }
    }
    
    let goldenStateWarriors = BasketballTeam(teamName: "Golden State Warriors")
    goldenStateWarriors.numberOfPlayers = 12
    goldenStateWarriors.locatedIn = "Oakland, California"
    goldenStateWarriors.roster = ["Stephen Curry" : 1, "Andrew Bogut" : 5, "Klay Thompson" : 2]
    goldenStateWarriors.roster["Harrison Barnes"] = 3
    
    goldenStateWarriors.printRoster()
    goldenStateWarriors.printTeamLocation()
    
    var num = 3
    
    if let numberToPositionConv = NumberedPosition(rawValue: num) {
        let description = numberToPositionConv.labelOfPosition()
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-05
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多