【发布时间】:2018-02-05 17:08:54
【问题描述】:
我有一个 java 类(称为 PhoneNumber)来验证和处理电话号码。
我自己编写了最后一个方法(删除可选的零),但我希望它更简单一些(可能使用正则表达式来识别可选的零并使用相同的正则表达式删除它,就像OPTIONAL_PHONE_NUMBER_CHARACTERS 部分)。这段代码感觉很脆弱而且不是 100% 正确,尽管我认为它可以满足我的需要并且涵盖了我能想到的所有单元测试。
谁能给我一个包含正确正则表达式的清晰示例? (也欢迎其他简单的解决方案)。
private static final Pattern VALID_PHONE_NUMBER_REGEX = Pattern.compile("\\+?[0-9#*]{1,20}");
private static final Pattern OPTIONAL_PHONE_NUMBER_CHARACTERS = Pattern.compile("[\\s()/.-]");
public static boolean isValid(String phoneNumber)
{
if (phoneNumber == null || phoneNumber.isEmpty())
{
return false;
}
String compactPhoneNumber = removeOptionalCharacters(phoneNumber);
return VALID_PHONE_NUMBER_REGEX.matcher(compactPhoneNumber).matches();
}
public static String removeOptionalCharacters(String phoneNumber)
{
String phoneNumberWithoutOptionalZero = removeOptionalZero(phoneNumber);
return OPTIONAL_PHONE_NUMBER_CHARACTERS.matcher(phoneNumberWithoutOptionalZero).replaceAll("");
}
private static final String OPTIONAL_ZERO = "(0)";
private static final String OPTIONAL_ZERO_SPLIT_REGEX = Pattern.quote("(0");
public static String removeOptionalZero(String phoneNumber)
{
String[] split = phoneNumber.split(OPTIONAL_ZERO_REGEX);
if (split.length == 2 && !split[0].isEmpty())
{
return phoneNumber.replaceAll(OPTIONAL_ZERO, "");
}
return phoneNumber;
}
如您所见,我提取了用于删除可选字符的代码,以防我需要使用电话号码拨打电话。例如。 +31 12-3456-789 会变成+31123456789。
我想使用 removeOptionalCharacters 方法进行的转换是:
+31 (0)12 3456 789 > +31123456789
+31 (012) 3456 789 > +31123456789
(0)12 3456 789 > 0123456789
(012) 3456 789 > 0123456789
总结一下,这些是应该成功的单元测试:
@Test
public void removeOptionalCharacters_HooksAroundOptionalZero_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+31 (0)12 3456789");
assertEquals("+31123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCode_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+31 (012) 3456789");
assertEquals("+31123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundOptionalZeroWithoutCountryCode_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(0)12 3456789");
assertEquals("0123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeWithoutCountryCode_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(012)3456789");
assertEquals("0123456789", compactPhoneNumber);
}
ps。我认为这些测试涵盖了所有带有可选零的常见情况。当然还有更多的单元测试来涵盖整个事情(3456789 部分还可以包括不应删除的零,并且其他可选字符(如 - 和 + 也不应该受到影响等),但为了简单起见,我已经离开了他们出去。如果您考虑电话号码,您将能够自己猜到其余的。
【问题讨论】:
-
+31 012 3456 789和+30 (0)12 3456 789号码呢? -
把这个提交给code review可能会更好。 “感觉脆弱”本身并不是真正的技术问题。你所拥有的基本上是有效的,但它可以做得更好。
-
阿努巴瓦,你是什么意思? +31 012 3456 789 没有区号,所以是有效的电话号码还是什么?也许您可以在解释中包含该示例的国家/地区?如果 +30 (0)12 3456 789 有 012 作为区号(所以“挂钩”0 是可选的),我希望它变成 +30123456789
-
MarsAtomic,真的,谢谢,我不知道网站的代码审查部分!因为“最佳答案”也值得商榷,所以我不会在这里指定一个,只有在我认为它对我有帮助的情况下才会投票。
标签: java android regex phone-number