我创建了一个String类型的枚举。它有两种初始化方法。一个是带有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
答案 0 :(得分:6)
您可以通过为switch
值和Int
之间的双向映射定义两个字典来摆脱enum case
语句。
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
}
}
答案 1 :(得分:1)
DávidPá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。
答案 2 :(得分: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))