1. 概述
有时我们需要处理以文本形式表达的电话号码,例如通过语音转文本接口获取的电话号码。本文将介绍一种算法,用于处理表示数字序列的单词序列,并将其转换为数字字符串。
2. 问题场景详解
输入的格式值得深入分析。我们可能会收到类似 "five six eight" 的电话号码单词形式。但实际口语中常包含倍数词,如 "double two"。因此算法需要处理以下转换:
输入: "triple five two three six eight"
预期输出: "5552368"
3. 使用switch语句实现算法
核心思路是将输入拆分为单词数组,逐个处理并构建输出结果。通过switch语句对单词分类处理。
3.1. 字符串拆分为单词数组
首先使用String.split()
方法按空格分割输入字符串:
String[] words = phoneNumberInWords.split(" ");
然后使用for-each循环遍历数组:
for (String word : words) {
// 处理逻辑
}
3.2. 处理倍数词
在循环中检查当前单词是否为倍数词:
Integer multiplier = getWordAsMultiplier(word);
if (multiplier != null) {
if (currentMultiplier != null) {
throw new IllegalArgumentException("不能出现连续的倍数词,错误位置: " + word);
}
currentMultiplier = multiplier;
}
通过getWordAsMultiplier()
方法映射倍数词:
public static Integer getWordAsMultiplier(String word) {
switch (word) {
case "double":
return 2;
case "triple":
return 3;
case "quadruple":
return 4;
default:
return null;
}
}
⚠️ 注意:连续倍数词(如"double triple")会抛出异常。
3.3. 处理非倍数词
当单词不是倍数词时,调用getWordAsDigit()
方法:
public static String getWordAsDigit(String word) {
switch (word) {
case "zero":
return "0";
case "one":
return "1";
...
case "nine":
return "9";
default:
throw new IllegalArgumentException("无效单词: " + word);
}
}
❌ 关键点:所有单词必须是数字词或倍数词,否则抛出异常。
3.4. 组装数字结果
使用StringBuilder
构建结果,根据倍数词重复数字:
if (multiplier != null) {
// 倍数词处理逻辑
} else {
output.append(getWordAsDigit(word)
.repeat(currentMultiplier != null ? currentMultiplier : 1));
currentMultiplier = null;
}
✅ 技巧:String.repeat()
方法轻松实现数字重复,默认重复1次。
3.5. 测试验证
验证三种场景:正确号码、无效单词、连续倍数词:
assertEquals("5248888",
SwitchConverter.convertPhoneNumberInWordToNumber("five two four quadruple eight"));
assertThrows(IllegalArgumentException.class, () -> {
SwitchConverter.convertPhoneNumberInWordToNumber("five eight invalid two four null eight");
});
assertThrows(IllegalArgumentException.class, () -> {
SwitchConverter.convertPhoneNumberInWordToNumber("five eight three double triple");
});
4. 使用Map替代switch语句
switch语句虽然有效但略显冗长,我们可以用Map优化实现。
4.1. 初始化数字和倍数映射
使用Map.of()
创建不可变映射:
private static Map<String, Integer> multipliers
= Map.of("double", 2, "triple", 3, "quadruple", 4);
private static Map<String, String> digits
= Map.of("zero", "0", "one", "1", "two", "2", "three", "3",
"four", "4", "five", "5", "six", "6", "seven", "7", "eight", "8", "nine", "9");
🛡️ 安全设计:使用不可变Map防止运行时修改导致错误。
4.2. 检查倍数词
直接通过Map获取倍数值:
Integer multiplier = multipliers.get(word);
4.3. 检查数字词
获取数字后验证有效性:
String digit = digits.get(word);
if (digit == null) {
throw new IllegalArgumentException("无效单词: " + word);
}
4.4. 测试验证
Map版本通过相同测试用例:
assertEquals("5248888",
MapConverter.convertPhoneNumberInWordToNumber("five two four quadruple eight"));
5. 总结
本文实现了两种电话号码单词转换方案:
- switch方案:逻辑直观但代码冗长
- Map方案:简洁高效,推荐生产使用
两种方案均能正确处理倍数词和数字词组合,并具备完善的错误处理机制。完整代码可在GitHub获取。