5 kyu
移動:從字元中「刪除」,再加上 ay。
以 replace 實作,利用正則驗證是否字首為 a-zA-z;在這一步如果是標點符號等則會被忽略,因為不會符合正則;符合正則的 match,則用變數暫存起來再字尾補上。
str.split
str.map(item =>
let str
item.replace(/^a-z/i, match =>
str = match
return ""
)
return item + str + "ay"
)
str.join(" ")
function pigIt(str) {
str = str.split(" ").map((item) => {
let str = "";
item = item.replace(/^[a-z]/i, (match) => {
str = match + "ay";
return "";
})
return item + str;
})
return str.join(" ");
}
split 拆解成陣列後,用 map 去迭代每一個陣列元素。/^[a-z]/i
會獲取字首的一個字元,驗證是否為 a-z 並且忽視字母大小寫。
如果有捕獲到 match,把符合的內容暫存變數並加上 ay;如果不符合正則的驗證,則不會進入這個函數。
將字首字元暫存後,返回空字串、也就是替代掉了首字元。
map 返回處理後,符合原始陣列長度的新陣列,這裡修正了 pseudo code 忽略的錯誤。return item + str + "ay"
這一段會把 ay 也加進標點符號之後,因此實作時把這段加到了 map 之中,外層宣告的 str 就會維持空字串。
最後返回 join 後的結果。
function pigIt(str){
return str.replace(/(\w)(\w*)(\s|$)/g, "\$2\$1ay\$3")
}
在正則表達式中,()
符號會拆分捕獲的條件。
(\w)
,尋找單一個 [A-Za-z0-9_]
,也就是字首字元。例如:Thing。(\w*)
,尋找出現零到多次的 [A-Za-z0-9_]
,也就是字首後的字元。例如:Thing。(\s|$)
,\s
表示空白、空格、換行等符號,$
表示結尾。replace 第二參數如果帶入函數,其中會帶入的參數:
replacer(match, $1, $2, /* …, */ $N, offset, string, groups)
整個正則表達式 /(\w)(\w*)(\s|$)/g
,會捕獲符合條件的字串,也就是 match; $1、$2 這種表示方式是對應第一參數的()
。
以 Hello world !
為例,match 會捕獲 "Hello "
以及 "world "
。
$1 $2 $3 分別是 "H"
、"ello"
、" "
, "w"
、"orld"
、" "
。
也就是說 \$2\$1ay\$3
,$1 在字首字元後加上 ay,並與 $2 調換位置,$3 則維持字尾的位置。
而其餘標點符號根本不會被正則捕獲,不受影響。
寫 pseudo code 的經驗還太少了,自己還沒辦法很好的運用。