iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
0
自我挑戰組

菜鳥工程師的奇幻漂流:跟著kata活化手指和意識系列 第 8

Decode the Morse code

今日kata

原始題目如下:(6kyu)
The Morse code encodes every character as a sequence of "dots" and "dashes". For example, the letter A is coded as ·−, letter Q is coded as −−·−, and digit 1 is coded as ·−−−−. The Morse code is case-insensitive, traditionally capital letters are used. When the message is written in Morse code, a single space is used to separate the character codes and 3 spaces are used to separate words. For example, the message HEY JUDE in Morse code is ···· · −·−− ·−−− ··− −·· ·.
NOTE: Extra spaces before or after the code have no meaning and should be ignored.

翻譯:
摩斯密碼由一連串的表示,例如A可以表示成.-Q可以表示成--.-。摩斯密碼不區分大小寫,通常使用大寫居多。當一段訊息用摩斯密碼表示時,用一個空格來分開每一個字母,用三個空格來分開每一個單字。例如HEY JUDE以摩斯密碼表示為:···· · −·−− ·−−− ··− −·· ·
註:頭尾的空白可忽略
另外Morse code table對照表已載入,可直接使用MORSE_CODE[morseCode]來查詢。Ex:MORSE_CODE['.--']會返回對應的字元。

範例:

decodeMorse('.... . -.--   .--- ..- -.. .')
//should return "HEY JUDE"

構想&解法

decodeMorse = function(morseCode) {
  morseCode = morseCode
  .split(' ')
  .map(cha => cha === '' ? '-' : MORSE_CODE[cha])

  return morseCode.join('').replace(/-+/g, ' ').trim()
}

input為字串形式,利用空格' '來拆分原始字串變成陣列。

'.... . -.--   .--- ..- -.. .'
拆成
["....", ".", "-.--", "", "", ".---", "..-", "-..", "."]

利用map()遍歷每一個元素cha,每一個元素都代表一個字母或是單字間的間隔
陣列中若含有空元素,代表原字串中有出現2個以上空格

map規則如下:

  • cha若為空元素,則取代成-
  • cha不為空元素,則呼叫MORSE_CODE返回對應字母

map完的陣列:['H','E','Y','-','-','J','U','D','E']
利用arr.join將陣列中所有元素組合成一個字串,並使用regex將有出現一個以上的-取代成空格


其他解法觀摩

decodeMorse = function(morseCode){
  function decodeMorseLetter(letter) {
    return MORSE_CODE[letter];
  }
  function decodeMorseWord(word) {
    return word.split(' ').map(decodeMorseLetter).join('');
  }
  return morseCode.trim().split('   ').map(decodeMorseWord).join(' ');
}

宣告兩個function,分別處理解碼字母(decodeMorseLetter)和解碼單字(decodeMorseWord)

  • morseCode原始輸入的字串先去處理頭尾空白trim()
  • 以三個空格為拆分條件,將字串拆解split(' ')
  • 每一單字再使用functiondecodeMorseWord解碼
  • function decodeMorseWord中會呼叫decodeMorseLetter解碼每一個字元
  • 最後join()陣列中的元素,返回完整的句子

也許不是最簡潔,但function功能區分得很乾淨,喜歡這樣的寫法


decodeMorse = function(morseCode){
  return morseCode.trim().split(' ').map(a => MORSE_CODE[a] || ' ').join('').replace(/\s+/g, ' ');
}

寫法和用法跟我原本的解法類似,method大概都是使用到trim()split()map()join()replace()以及regex正規表示式。寫法又再更簡潔! (還是習慣多宣告一個變數存放要return的值....)


整理用法

邁入第8天遇到了不少處理字串的方法,一起做個整理

方法 語法 回傳 範例 備註
includes() str.includes(搜尋字串[,搜尋位置]) true/false 'I love my job'.includes('Love')// false 大小寫有別
indexOf() str.indexOf(搜尋字串[,搜尋位置]) 字元出現位置/-1(找不到) 'I love my job'.indexOf('l') // 2 大小寫有別&由左至右搜尋
match() str.match(正規表示物件) 陣列(包含符合的內容) 'I love my job'.match(/[love]/g) // ["l", "o", "v", "e", "o"] -
repeat() str.repeat(次數) 新字串 'I love my job'.repeat(2) // "I love my jobI love my job" -
replace() newStr=str.replace(正規表示|搜尋字串,取代字串|函式) 新字串
slice() str.slice(起始位置[,結束位置]) 新字串 'I love my job'.slice(2,6) // love 結束位置的字元不算在內
split() str.split([切割字元[,限制輸出的元素個數]]) 陣列(切割完的結果) 'I love my job'.split(' ',2) // ["I", "love"] -
substring() str.substring(擷取起始位置[,擷取結束位置]) 新字串 'I love my job'.substring(2,6) // love 若傳入的起始位置>結束位置,substring()會自動交換,能正常回傳新字串;同樣的情境slice()會回傳空字串
toLowerCase() str.toLowerCase() 新字串(轉小寫) 'I love my job'.toLowerCase() // "i love my job" -
toUpperCase() str.toUpperCase() 新字串(轉大寫) 'I love my job'.toUpperCase() // "I LOVE MY JOB" -
trim() str.trim() 新字串(去頭尾空白) ' I love my job '.trim() // "I love my job" -

因為Strings are immutable (不可變),處理字串相關的方法都不會改變原字串,一定都是返回一個新的字串。

以上為今日分享的內容,若有錯誤或是建議,請再隨時和我聯繫


上一篇
Sum of Digits / Digital Root
下一篇
Counting Duplicates
系列文
菜鳥工程師的奇幻漂流:跟著kata活化手指和意識30

尚未有邦友留言

立即登入留言