如何使用Swift验证String
是否使用类似123-45-6789
的模式编码有效的美国社会安全号码(SSN)?
验证意味着检查给定字符串是否与模式123-45-6789
匹配。
答案 0 :(得分:4)
<强>简单地:强>
步骤1。创建一个方法:
func isValidSsn(_ ssn: String) -> Bool {
let ssnRegext = "^(?!(000|666|9))\\d{3}-(?!00)\\d{2}-(?!0000)\\d{4}$"
return ssn.range(of: ssnRegext, options: .regularExpression, range: nil, locale: nil) != nil
}
第二步。使用它:
let ssn = "123-45-6789"
validateSsn(ssn) // true
希望它有所帮助!
答案 1 :(得分:0)
最好为此使用自定义类型。它有一个可用的初始值设定项,可用于从String初始化它。一旦你有一个非零的SSN实例,你知道它是一个有效的SSN,你永远不需要再次检查。
我正在将SSN解析为UInt32
,并在必要时将其序列化为字符串。这可以防止与分配和传递字符串相关的ARC和堆存储开销。这是实施:
import Foundation
struct SSN {
// Stores aaa-bb-ccc as aaabbbccc
let ssn: UInt32
init?(_ string: String) {
let segments = string.split(separator: "-")
guard segments.lazy.map({ $0.count }) == [3, 2, 3] else {
debugPrint("SSN segments must be lenght 3, 2, 3 (e.g. 123-45-678).")
return nil
}
guard !zip(segments, ["000", "00", "000"]).contains(where: {$0.0 == $0.1}) else {
debugPrint("SSN segments cannot be all zeros.")
return nil
}
let firstSegment = segments[0]
guard firstSegment != "666", !firstSegment.hasPrefix("9") else {
debugPrint("The first SSN segment (\(firstSegment)) cannot be 666, or be in the range 900-999.")
return nil
}
let dashesRemoved = string.replacingOccurrences(of: "-", with: "")
self.ssn = UInt32(dashesRemoved)!
}
}
extension SSN: ExpressibleByStringLiteral {
init(stringLiteral literalString: String) {
self.init(literalString)!
}
}
extension SSN: CustomStringConvertible {
var description: String {
let formatter = NumberFormatter()
formatter.minimumIntegerDigits = 3
let segment1 = formatter.string(from: NSNumber(value: self.ssn / 100000))!
formatter.minimumIntegerDigits = 2
let segment2 = formatter.string(from: NSNumber(value: (self.ssn / 1000) % 100))!
formatter.minimumIntegerDigits = 3
let segment3 = formatter.string(from: NSNumber(value: self.ssn % 1000))!
return "\(segment1)-\(segment2)-\(segment3)"
}
}
还有一些测试:
let testSSNString = "123-45-678"
let optionalTestSSN = SSN(testSSNString)
guard let testSSN = optionalTestSSN else {
assertionFailure("Valid SSN (\(testSSNString)) wasn't successfully parsed.")
fatalError()
}
assert(testSSN.description == testSSNString, "SSN (\(testSSN)) was not correctly converted back to String.")
func assertSSNShouldBeNil(_ string: String, because reason: String) {
assert(SSN(string) == nil, reason + " should be nil.")
}
assertSSNShouldBeNil("123-45-678-9", because: "SSN with too many segment")
assertSSNShouldBeNil("123-45", because: "SSN with too few segments")
assertSSNShouldBeNil("", because: "Empty SSN")
assertSSNShouldBeNil("000-12-345", because: "SSN with all-zero segment 1")
assertSSNShouldBeNil("123-00-456", because: "SSN with all-zero segment 2")
assertSSNShouldBeNil("123-45-000", because: "SSN with all-zero segment 3")
assertSSNShouldBeNil("666-12-345", because: "SSN starting with 666")
assertSSNShouldBeNil("900-12-345", because: "SSN starting with number in range 900-999")
assertSSNShouldBeNil("999-12-345", because: "SSN starting with number in range 900-999")