Ios Swift:如何验证社会保险号(SSN)?
我如何使用Swift验证Ios Swift:如何验证社会保险号(SSN)?,ios,swift,regex,Ios,Swift,Regex,我如何使用Swift验证字符串是否编码了一个有效的美国社会保险号码(SSN),其模式类似于123-45-6789 验证意味着检查给定字符串是否与模式匹配123-45-6789简单地说: 第一步。创建一个方法: func isValidSsn(_ ssn: String) -> Bool { let ssnRegext = "^(?!(000|666|9))\\d{3}-(?!00)\\d{2}-(?!0000)\\d{4}$" return ssn.range(of: ssnReg
字符串
是否编码了一个有效的美国社会保险号码(SSN),其模式类似于123-45-6789
验证意味着检查给定字符串是否与模式匹配
123-45-6789
简单地说:
第一步。创建一个方法:
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
希望有帮助 简单地说: 第一步。创建一个方法:
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
希望有帮助 最好为此使用自定义类型。它有一个可失败的初始值设定项,可用于从字符串初始化它。一旦您拥有一个SSN的非nil实例,您就知道它是一个有效的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")
最好为此使用自定义类型。它有一个可失败的初始值设定项,可用于从字符串初始化它。一旦您拥有一个SSN的非nil实例,您就知道它是一个有效的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")
真的没有理由立即投票,对吗?只是查了一下,发现SSN没有校验位。哈哈,真是个笑话。@Alexander我的尝试在答案中。你仍然认为它应该被否决吗?我只是觉得这个问题可能经常被问到,这就是为什么我做了QA,这也是StackOverflow很欣赏的。我不明白是什么问题。@TungFam哦,我没注意到。我将推翻我的投票。仅供参考-自答问题仍然需要完全符合SO的标准。这个问题没有表现出任何努力,没有研究,也不清楚这个问题到底在解决什么样的编码问题。这个问题需要和其他任何问题一样写出来,这样任何人都可以回答,而不仅仅是问题的作者。真的没有理由立即投票,对吗?只是查了一下,了解到SSN没有校验位。哈哈,真是个笑话。@Alexander我的尝试在答案中。你仍然认为它应该被否决吗?我只是觉得这个问题可能经常被问到,这就是为什么我做了QA,这也是StackOverflow很欣赏的。我不明白是什么问题。@TungFam哦,我没注意到。我将推翻我的投票。仅供参考-自答问题仍然需要完全符合SO的标准。这个问题没有表现出任何努力,没有研究,也不清楚这个问题到底在解决什么样的编码问题。这个问题需要和其他任何问题一样写出来,这样任何人都可以回答,而不仅仅是问题的作者。在字符串中添加一个扩展名是解决这个问题的一种非常非常繁重的方法。我认为如果扩展名对你不起作用,你可以把它从扩展名中去掉@塔德马尼认为你给出了一个解决方案,但如果人们不理解它的含义,这可能会导致很多问题。为什么这个简单的Swift方法不能接受字符串参数呢?我同意这个版本更容易理解,但是没有理由对字符串进行扩展。如果由我决定,我可能会在
私有扩展字符串中添加一个func isvalidsn()->Bool
。最好创建一个自定义类型,以确保其在初始化时有效(可失败的初始值设定项),并在向字符串添加扩展后保持不变,解决这个问题的方法真的很严厉。我想如果它对你不起作用,你可以把它从扩展中去掉@塔德马尼认为你给出了一个解决方案,但如果人们不理解它的含义,这可能会导致很多问题。为什么这个简单的Swift方法不能接受字符串参数呢?我同意这个版本更容易理解,但是没有理由对字符串进行扩展。如果由我决定,我可能会在私有扩展字符串中添加一个func isvalidsn()->Bool
。最好创建一个自定义类型,以确保其在初始化时有效(可失败的初始值设定项),并在初始化后保持不变