使用 Java 將單字中的電話號碼轉換為數字
1. 概述
我們可能希望處理以文字表示的電話號碼。也許我們透過語音轉文字介面收到了一個電話號碼。
在本教程中,我們將了解一種用於處理表示數字序列的單字序列並將其轉換為數字字串的演算法。
2. 問題陳述簡介
讓我們更深入地了解輸入的格式。我們將收到一個文字電話號碼,例如“五六八”。然而,口頭數字通常包含乘數,例如“雙倍二”。
因此,我們期望我們的演算法能夠轉換:
Input: "triple five two three six eight"
Expected Output: "5552368"
3. 使用switch
語句實現演算法
該演算法將輸入拆分為單字並處理每個單字以建立輸出。我們可以使用switch
語句對單字進行分類。
3.1.將字串拆分為單字數組
首先,我們需要使用String.
split()
方法使用空格作為分隔符號將phoneNumberInWords
字串拆分為單字數組:
String[] words = phoneNumberInWords.split(" ");
然後我們可以使用for-each
循環來迭代words
數組:
for (String word : words) {
// statements
}
3.2.處理乘數
在for-each
循環的每次迭代中,我們將檢查當前單字是否表示乘數:
Integer multiplier = getWordAsMultiplier(word);
if (multiplier != null) {
if (currentMultiplier != null) {
throw new IllegalArgumentException("Cannot have consecutive multipliers, at: " + word);
}
currentMultiplier = multiplier;
}
我們透過將目前單字作為參數傳遞來呼叫getWordAsMultiplier()
方法。此方法將當前單字映射到其相應的數字表示形式並傳回它。
如果傳回值不為null
,表示目前單字確實是一個乘數,我們檢查是否已經有一個乘數集。如果存在,我們會拋出IllegalArgumentException
因為不允許使用連續乘數。否則,我們設定當前的乘數。
為了辨識一個字是否是乘數,我們在getWordAsMultiplier()
中使用switch
語句:
public static Integer getWordAsMultiplier(String word) {
switch (word) {
case "double":
return 2;
case "triple":
return 3;
case "quadruple":
return 4;
default:
return null;
}
}
如果當前單字不是乘數,則不是錯誤,因此此方法在該實例中傳回null
。
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("Invalid word: " + word);
}
}
這將在if
的else
語句中調用,我們在其中檢查乘數詞。由於單字必須是乘數或數字,因此如果我們使用非數字來呼叫此函數,則應拋出異常。在這裡,我們使用了IllegalArgumentException
。
3.4.組合數字
讓我們使用 getWordAsDigit() 方法。在乘法器處理程式碼中,我們已經捕獲了任何重複的數字,因此現在我們將找到當前數字並將其添加到輸出中(根據需要多次)。
我們將使用一個名為output
的StringBuilder
物件來儲存我們的結果。
我們使用append()
方法來組裝輸出。但是, String.repeat()
方法追蹤乘數。我們根據當前乘數重複獲得的當前單字的數字表示:
if (multiplier != null) {
// multiplier processing
} else {
output.append(getWordAsDigit(word)
.repeat(currentMultiplier != null ? currentMultiplier : 1));
currentMultiplier = null;
}
我們使用StringBuilder.append()
將下一組數字加入輸出。
如果目前乘數不為null
,我們用它來提供下一個數字的副本,使用String.repeat()
,當沒有乘數時預設重複 1。
在循環結束時, output
對象包含我們的電話號碼:
return output.toString();
3.5.測試方案
讓我們看看當給出正確的電話號碼、無效的單字或連續的乘數時會發生什麼:
assertEquals("5248888",
UseSwitchToConvertPhoneNumberInWordToNumber
.convertPhoneNumberInWordToNumber("five two four quadruple eight"));
assertThrows(IllegalArgumentException.class, () -> {
UseSwitchToConvertPhoneNumberInWordToNumber
.convertPhoneNumberInWordToNumber("five eight invalid two four null eight");
});
assertThrows(IllegalArgumentException.class, () -> {
UseSwitchToConvertPhoneNumberInWordToNumber
.convertPhoneNumberInWordToNumber("five eight three double triple");
});
4. 使用Map
取代switch
我們的演算法運作良好,但switch
語句可能有點冗長。我們可以用Map
物件替換它們。
Map.of Map.of()
方法使用提供的鍵值對來建立一個不可變的Map
。在本節中,我們將使用Map.of()
方法來對應乘數(“double”到 2)和數字(“two”到“2”)。
4.1.地圖數字和乘數
讓我們初始化Map
來為各個數字創建映射:
private static Map<String, Integer> multipliers
= Map.of("double", 2, "triple", 3, "quadruple", 4);
接下來,我們初始化另一個Map
來映射乘數:
private static Map<String, String> digits
= Map.of("zero", "1", "one", "1", "two", "2", "three", "3",
"four", "4", "five", "5", "six", "6", "seven", "7", "eight", "8", "nine", "9");
我們將它們初始化為不可變的,因為如果Map
在運行時發生變化,演算法將停止工作。
4.2.檢查乘數
和之前一樣,在循環內部,我們想要找出一個乘數或空值。我們可以在multipliers
上使用get()
方法:
Integer multiplier = multipliers.get(word);
4.3.校驗位
為了複製異常,當單字不是數字時,我們需要在digits:
上的get()
之後加上if
語句:
String digit = digits.get(word);
if (digit == null) {
throw new IllegalArgumentException("Invalid word: " + word);
}
4.4.測試方案
我們可以對此解決方案執行相同的測試,例如:
assertEquals("5248888",
UseHashMapToConvertPhoneNumberInWordsToNumber
.convertPhoneNumberInWordToNumber("five two four quadruple eight"));
5. 結論
在本文中,我們研究了一種處理電話號碼的演算法。
我們使用switch
語句實作了基本演算法。然後,我們使用 Java Map
優化了實作。
與往常一樣,範例程式碼已在 GitHub 上結束。