我已经用字符串类型装了一个枚举。它有两个初始化方法。一个是带有 rawValue 的默认 init 方法,另一个是带有 intValue 的自定义 init 方法。我是这样写的。有没有简单的方法不使用两个开关盒?
enum Roman: String {
case I,V,X,L,C,D,M
var intValue: Int {
switch self {
case .I:
return 1
//...
}
}
init?(intValue: Int) {
switch intValue {
case 1:
self = .I
//...
default:
return nil
}
}
}
//Roman to Int
let number = "XXI".reversed()
.map { Roman(rawValue: String($0))?.intValue ?? 0 }
.reduce((total: 0, max: 0)) { result, value in
let newTotal = result.total + (value < result.max ? -value : value)
return (newTotal, max(result.max, value))
}.total
为Int
值和enum case
之间的双向映射定义两个字典来摆脱switch
语句。
enum Roman: String {
case I, V, X, L, C, D, M
private static let intValues:[Roman:Int] = [.I:1,.V:5,.X:10,.L:50,.C:100,.D:500,.M:1000]
private static let mappingDict:[Int:Roman] = Dictionary(uniqueKeysWithValues: Roman.intValues.map({ ($1, $0) }))
var intValue:Int {
return Roman.intValues[self]!
}
init?(intValue:Int){
guard let roman = Roman.mappingDict[intValue] else { return nil }
self = roman
}
}
Dávid Pásztor的回答没有错,但我真的很喜欢Βασίλης Δ.的思维原始值。这似乎是一种非常自然的方法。所以我想把这些放在一起。
首先,从 Βασίλης Δ. 的代码开始,添加一个 intValue
别名,因为我认为它读起来更好一些。
enum Roman: Int {
case I = 1
case V = 5
case X = 10
case L = 50
case C = 100
case D = 500
case M = 1000
var intValue: Int { return rawValue }
}
然后使用新的 CaseIterable 提供字符串查找:
extension Roman: CaseIterable {
enum Error: Swift.Error {
case invalid
}
init<S: StringProtocol>(_ string: S) throws {
guard let roman = Roman.allCases.first(where: { "($0)" == string }) else {
throw Error.invalid
}
self = roman
}
init(_ character: Character) throws { try self.init(String(character)) }
}
有了这个,我认为number
算法在顶部变得更好一些:
let number = try "XXI".reversed()
.map { try Roman($0).intValue }
.reduce((total: 0, max: 0)) { result, value in
let newTotal = result.total + (value < result.max ? -value : value)
return (newTotal, max(result.max, value))
}.total
我不是这个算法的忠实粉丝,因为它对无效输入的行为不规则,但至少这个版本拒绝无效字符而不是将它们转换为 0。
如果我理解正确的话,你想要什么..为什么不直接将值分配给枚举器事例?前任。
enum Roman: Int {
case I = 1
case V = 5
case X = 10
case L = 50
case C = 100
case D = 500
case M = 1000
}
在你的主课上
print(Roman.I.rawValue)
print(Roman(rawValue: 1))