javascript 我如何验证澳大利亚医疗保险号码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3589345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I validate an Australian Medicare number?
提问by Jonathan
I'm developing an online form in which user-entered Medicare numbers will need to be validated.
我正在开发一个在线表格,需要验证用户输入的医疗保险号码。
(My specific problem concerns Australian Medicare numbers, but I'm happy for answers regarding American ones too. This question is about Medicare numbers in general.)
(我的具体问题与澳大利亚医疗保险号码有关,但我也很高兴能得到有关美国医疗保险号码的答案。这个问题一般与医疗保险号码有关。)
So how should I do it?
那我该怎么做呢?
(It would be good to have the answer in Javascript or a regex.)
(最好在 Javascript 或正则表达式中得到答案。)
回答by user2247167
The regex supplied by Jeffrey Kemp (March 11) would help to validate the allowed characters, but the check algorithm below should be enough to validate that the number conforms to Medicare's rules.
Jeffrey Kemp(3 月 11 日)提供的正则表达式将有助于验证允许的字符,但下面的检查算法应该足以验证数字是否符合 Medicare 的规则。
The Medicare card number comprises:
Medicare 卡号包括:
- Eight digits;
- A check digit (one digit); and
- An issue number (one digit).
- 八位数字;
- 一个校验位(一位);和
- 问题编号(一位)。
Note: the first digit of the Medicare card number should be in the range 2 to 6.
注意:Medicare 卡号的第一位数字应在 2 到 6 之间。
Medicare card number check digit calculation
医保卡号校验位计算
- Calculate the sum of: ((digit 1) + (digit 2 * 3) + (digit 3 * 7) + (digit 4 * 9) + (digit 5) + (digit 6 * 3) + (digit 7 * 7) + (digit 8 * 9))
- 计算总和:((digit 1) + (digit 2 * 3) + (digit 3 * 7) + (digit 4 * 9) + (digit 5) + (digit 6 * 3) + (digit 7 * 7) +(数字 8 * 9))
where digit 1 is the highest place value digit of the Medicare card number and digit 8 is the lowest place value digit of the Medicare card number.
其中,数字 1 是医疗保险卡号的最高位值数字,数字 8 是医疗保险卡号的最低位值数字。
Example:for Medicare card number '2123 45670 1', digit 1 is 2 and digit 8 is 7.
示例:对于 Medicare 卡号“2123 45670 1”,数字 1 为 2,数字 8 为 7。
- Divide the calculated sum by 10.
- The check digit is the remainder.
- 将计算出的总和除以 10。
- 校验位是余数。
Example:For Medicare card number 2123 4567.
示例:对于医疗保险卡号码 2123 4567。
- (2) + (1 * 3) + (2 * 7) + (3 * 9) + (4) + (5 * 3) + (6 * 7) + (7 * 9) = 170
- Divide 170 by 10. The remainder is 0.
- The check digit for this Medicare number is 0.
- (2) + (1 * 3) + (2 * 7) + (3 * 9) + (4) + (5 * 3) + (6 * 7) + (7 * 9) = 170
- 170 除以 10,余数为 0。
- 此 Medicare 号码的校验位是 0。
Source: "Use of Healthcare Identifiers in Health Software Systems - Software Conformance Requirements, Version 1.4", NEHTA, 3/05/2011
来源:“在健康软件系统中使用医疗保健标识符 - 软件一致性要求,版本 1.4”,NEHTA,3/05/2011
回答by Daniel Orme?o
If you are looking for a C# version, give this a try:
如果您正在寻找 C# 版本,请尝试一下:
using System.Linq;
//...
public bool IsMedicareFormatValid(string medicareNumber)
{
if (!(medicareNumber?.Length >= 10 && medicareNumber.Length <12) || !medicareNumber.All(char.IsDigit))
return false;
var digits = medicareNumber.Select(c => (int) char.GetNumericValue(c)).ToArray();
return digits[8] == GetMedicareChecksum(digits.Take(8).ToArray());
}
private int GetMedicareChecksum(int[] digits)
{
return digits.Zip(new[] { 1, 3, 7, 9, 1, 3, 7, 9 }, (m, d) => m*d).Sum() % 10;
}
Note:This will return false for null values, you might want to throw an exception.
注意:对于空值,这将返回 false,您可能想要抛出异常。
To clarify:
澄清:
- The first 9 Numbers in the medicare card would correspond to the actual medicare number (used in the check).
- The 9th digit is a check digit calculated in the
GetMedicareChecksummethod. - The 10th digit identifies the number of the card, so if you've been issued 3 cards (because you've lost it or whatever), the number would be 3
- The 11th digit would identify the family member inside the group.
- 医疗保险卡中的前 9 个数字将对应于实际医疗保险编号(用于支票)。
- 第9位是该
GetMedicareChecksum方法计算的校验位。 - 第 10 位数字标识卡的编号,因此如果您已获得 3 张卡(因为您丢失或其他原因),则编号为 3
- 第 11 位数字将标识组内的家庭成员。
Hope someone finds this useful.
希望有人觉得这很有用。
回答by David Rees
Added Java Version
添加了 Java 版本
public static boolean isMedicareValid(String input, boolean validateWithIRN){
int[] multipliers = new int[]{1, 3, 7, 9, 1, 3, 7, 9};
String pattern = "^(\d{8})(\d)";
String medicareNumber = input.replace(" " , "");
int length = validateWithIRN ? 11 : 10;
if (medicareNumber.length() != length) {return false;}
Pattern medicatePattern = Pattern.compile(pattern);
Matcher matcher = medicatePattern.matcher(medicareNumber);
if (matcher.find()){
String base = matcher.group(1);
String checkDigit = matcher.group(2);
int total = 0;
for (int i = 0; i < multipliers.length; i++){
total += base.charAt(i) * multipliers[i];
}
return ((total % 10) == Integer.parseInt(checkDigit));
}
return false;
}
回答by Jeffrey Kemp
My Australian Medicare number is 11 numeric digits and includes no letters or other characters.
我的澳大利亚医疗保险号码是 11 位数字,不包含字母或其他字符。
It is formatted in groups, and the last digit varies according to the member of my family, e.g.:
它是按组格式化的,最后一位数字因我的家庭成员而异,例如:
- Me:
5101 20591 8-1 - My wife:
5101 20591 8-2 - My first child:
5101 20591 8-3
- 我:
5101 20591 8-1 - 我的妻子:
5101 20591 8-2 - 我的第一个孩子:
5101 20591 8-3
I've seen medicare numbers formatted without the spaces and the dash, but the meaning is the same, so I'd expect to accept 51012059181as a valid Medicare number as well.
我见过格式不带空格和破折号的医疗保险号码,但含义是一样的,所以我也希望接受51012059181有效的医疗保险号码。
I've also seen context where the last digit is not required or not supposed to be entered; e.g. 5101205918, I guess where they're only interested in the family as a whole.
我还看到了不需要或不应该输入最后一位数字的上下文;例如5101205918,我猜他们只对整个家庭感兴趣。
Therefore, I think this may be appropriate:
因此,我认为这可能是合适的:
^\d{4}[ ]?\d{5}[ ]?\d{1}[- ]?\d?$
EDIT
编辑
Based on the logic in user2247167's answer, I've used the following PL/SQL function in my Apex application to give a user-friendly warning to the user:
根据 user2247167 的回答中的逻辑,我在我的 Apex 应用程序中使用了以下 PL/SQL 函数来向用户提供用户友好的警告:
FUNCTION validate_medicare_no (i_medicare_no IN VARCHAR2)
RETURN VARCHAR2 IS
v_digit1 CHAR(1);
v_digit2 CHAR(1);
v_digit3 CHAR(1);
v_digit4 CHAR(1);
v_digit5 CHAR(1);
v_digit6 CHAR(1);
v_digit7 CHAR(1);
v_digit8 CHAR(1);
v_check CHAR(1);
v_result NUMBER;
BEGIN
IF NOT REGEXP_LIKE(i_medicare_no, '^\d{10}\d?{2}$') THEN
RETURN 'Must be 10-12 digits, no spaces or other characters';
ELSE
v_digit1 := SUBSTR(i_medicare_no, 1, 1);
IF v_digit1 NOT IN ('2','3','4','5','6') THEN
RETURN 'Not a valid Medicare number - please check and re-enter';
ELSE
v_digit2 := SUBSTR(i_medicare_no, 2, 1);
v_digit3 := SUBSTR(i_medicare_no, 3, 1);
v_digit4 := SUBSTR(i_medicare_no, 4, 1);
v_digit5 := SUBSTR(i_medicare_no, 5, 1);
v_digit6 := SUBSTR(i_medicare_no, 6, 1);
v_digit7 := SUBSTR(i_medicare_no, 7, 1);
v_digit8 := SUBSTR(i_medicare_no, 8, 1);
v_check := SUBSTR(i_medicare_no, 9, 1);
v_result := mod( to_number(v_digit1)
+ (to_number(v_digit2) * 3)
+ (to_number(v_digit3) * 7)
+ (to_number(v_digit4) * 9)
+ to_number(v_digit5)
+ (to_number(v_digit6) * 3)
+ (to_number(v_digit7) * 7)
+ (to_number(v_digit8) * 9)
,10);
IF TO_NUMBER(v_check) != v_result THEN
RETURN 'Not a valid Medicare number - please check and re-enter';
END IF;
END IF;
END IF;
-- no error
RETURN NULL;
END validate_medicare_no;
回答by user2943490
The accepted answer, adapted to JavaScript:
接受的答案,适用于 JavaScript:
var validator = function (input, validateWithIrn) {
if (!input) {
return false;
}
var medicareNumber;
var pattern;
var length;
var matches;
var base;
var checkDigit;
var total;
var multipliers;
var isValid;
pattern = /^(\d{8})(\d)/;
medicareNumber = input.toString().replace(/ /g, '');
length = validateWithIrn ? 11 : 10;
if (medicareNumber.length === length) {
matches = pattern.exec(medicareNumber);
if (matches) {
base = matches[1];
checkDigit = matches[2];
total = 0;
multipliers = [1, 3, 7, 9, 1, 3, 7, 9];
for (var i = 0; i < multipliers.length; i++) {
total += base[i] * multipliers[i];
}
isValid = (total % 10) === Number(checkDigit);
} else {
isValid = false;
}
} else {
isValid = false;
}
return isValid;
};
回答by David Rees
Added Swift version
添加了 Swift 版本
class func isMedicareValid(input : String, validateWithIrn : Bool) -> Bool {
let multipliers = [1, 3, 7, 9, 1, 3, 7, 9]
let pattern = "^(\d{8})(\d)"
let medicareNumber = input.removeWhitespace()
let length = validateWithIrn ? 11 : 10
if medicareNumber.characters.count != length {return false}
let expression = try! NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive)
let matches = expression.matchesInString(medicareNumber, options: NSMatchingOptions.ReportProgress, range: NSMakeRange(0, length))
if (matches.count > 0 && matches[0].numberOfRanges > 2) {
let base = medicareNumber.substringWithRange(medicareNumber.startIndex...medicareNumber.startIndex.advancedBy(matches[0].rangeAtIndex(1).length))
let checkDigitStartIndex = medicareNumber.startIndex.advancedBy(matches[0].rangeAtIndex(2).location )
let checkDigitEndIndex = checkDigitStartIndex.advancedBy(matches[0].rangeAtIndex(2).length)
let checkDigit = medicareNumber.substringWithRange(checkDigitStartIndex..<checkDigitEndIndex)
var total = 0
for i in 0..<multipliers.count {
total += Int(base.charAtIndex(i))! * multipliers[i]
}
return (total % 10) == Int(checkDigit)
}
return false
}
I use some String extensions as well to simplify some operations.
我也使用一些字符串扩展来简化一些操作。
extension String {
func charAtIndex (index: Int) -> String{
var character = ""
if (index < self.characters.count){
let locationStart = self.startIndex.advancedBy(index)
let locationEnd = self.startIndex.advancedBy(index + 1 )
character = self.substringWithRange(locationStart..<locationEnd)
}
return character
}
func replace(string:String, replacement:String) -> String {
return self.stringByReplacingOccurrencesOfString(string, withString: replacement, options: NSStringCompareOptions.LiteralSearch, range: nil)
}
func removeWhitespace() -> String {
return self.replace(" ", replacement: "")
}
}
回答by Abubakar Riaz
You can create Validation Attribute to validate Medicare number
您可以创建验证属性来验证医疗保险号码
You can use it by
您可以通过以下方式使用它
[AustralianMedicareNumberOnly]
public string MedicareNo { get; set; }
Code
代码
public class AustralianMedicareNumberOnlyAttribute : ValidationAttribute
{
private string exampleNumber = "Example: 2234 56789 1-2";
public AustralianMedicareNumberOnlyAttribute()
{
ErrorMessage = string.Concat("{0} is not in correct format, ", exampleNumber);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
string objectValueString;
int[] checksumDigits = new int[] { 1, 3, 7, 9, 1, 3, 7, 9 };
int checksumDigit;
int checksumtotal = 0;
int checksumDigitCalculated;
//convert incomming object value to string
objectValueString = Convert.ToString(value).Trim();
// check medicare number format should be 1234 56789 1-2
if (!Regex.IsMatch(objectValueString, @"^[2-6]\d{3}\s\d{5}\s\d{1}-\d{1}$"))
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
else
{
//Check checksum value
//--------------------
// replace two spaces and one dash
objectValueString = objectValueString.Replace(" ", "").Replace("-", "");
// Calculate the sum of: ((digit 1) + (digit 2 * 3) + (digit 3 * 7) + (digit 4 * 9) + (digit 5) + (digit 6 * 3) + (digit 7 * 7) + (digit 8 * 9))
for (int i = 0; i < checksumDigits.Length; i++)
{
int digit = Convert.ToInt32(objectValueString.Substring(i, 1));
checksumtotal += digit * checksumDigits[i];
}
//find out checksum digit
checksumDigit = Convert.ToInt32(objectValueString.Substring(8, 1));
checksumDigitCalculated = checksumtotal % 10;
// check calculated checksum with medicare checksum digit
if (checksumDigit!= checksumDigitCalculated)
{
return new ValidationResult("The Medicare Number is not Valid.");
}
}
}
return ValidationResult.Success;
}
}
回答by Ben Gulapa
Here's a Typescript or modern Javascript solution:
这是一个 Typescript 或现代 Javascript 解决方案:
validateMedicare(medicare) {
let isValid = false;
if (medicare && medicare.length === 10) {
const matches = medicare.match(/^(\d{8})(\d)/);
if (!matches) {
return { invalid: true };
}
const base = matches[1];
const checkDigit = matches[2];
const weights = [1, 3, 7, 9, 1, 3, 7, 9];
let sum = 0;
for (let i = 0; i < weights.length; i++) {
sum += parseInt(base[i], 10) * weights[i];
}
isValid = sum % 10 === parseInt(checkDigit, 10);
}
return isValid;
}
Please refer to http://clearwater.com.au/code/medicarefor an explanation.
请参阅http://clearwater.com.au/code/medicare以获得解释。
To test, generate medicare number here: https://precedencehealthcare.com/rmig/
要进行测试,请在此处生成医疗保险编号:https: //precedencehealthcare.com/rmig/
回答by David Rees
Added Dart version:
添加了 Dart 版本:
bool isMedicareValid(String input, {bool validateWithIrn = true}) {
final medicareNumber = input.replaceAll(" ", "");
final length = validateWithIrn ? 11 : 10;
if (medicareNumber.length != length) {
return false;
}
final multipliers = [1, 3, 7, 9, 1, 3, 7, 9];
final regexp = RegExp("^(\d{8})(\d)", caseSensitive: false);
final matches = regexp.allMatches(medicareNumber).toList();
if (matches.length > 0 && matches[0].groupCount >= 2) {
final base = matches[0].group(1);
final checkDigit = matches[0].group(2);
var total = Iterable.generate(multipliers.length)
.fold(0, (current, index) => current += (int.tryParse(base[index]) * multipliers[index]));
return (total % 10) == int.parse(checkDigit);
}
return false;
}
回答by Manager DMT
You can use simple regex validation: .replace(/\W/gi, "") .replace(/(.{4})(.{5})/g, "$1 $2 ");
您可以使用简单的正则表达式验证: .replace(/\W/gi, "") .replace(/(.{4})(.{5})/g, "$1 $2 ");
check my example here: codesandbox.io
在此处查看我的示例: codesandbox.io

