原始題目如下:(5kyu)
… a man was given directions to go from one point to another. The directions were "NORTH", "SOUTH", "WEST", "EAST". Clearly "NORTH" and "SOUTH" are opposite, "WEST" and "EAST" too.
Going to one direction and coming back the opposite direction right away is a needless effort. Since this is the wild west, with dreadfull weather and not much water, it's important to save yourself some energy, otherwise you might die of thirst!
翻譯:
有一份方位指示,是一連串的東西南北組合,其中東-西
南-北
為相反方向,相反方向相鄰
的指示存在,是不必要的,也為了行路人(?)的體力著想,請協助重新整理這份指南。
範例:
["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"] ==> ["WEST"]
["EAST", "EAST", "WEST", "NORTH", "WEST", "EAST", "EAST", "SOUTH", "NORTH", "WEST"] ==> ["EAST", "NORTH"]
同理消括號
系列題目,NORTH
SOUTH
相鄰要消除、EAST
WEST
相鄰要消除!
function dirReduc(arr) {
let pair = {
'NORTH': 'SOUTH',
'SOUTH': 'NORTH',
'WEST': 'EAST',
'EAST': 'WEST'
}
let stack = []
for (let i = 0; i < arr.length; i++) {
stack.length === 0 ? stack.push(arr[i]) :
pair[(stack[stack.length-1])] === arr[i] ? stack.pop() : stack.push(arr[i])
}
return stack
}
解法類似找出括號是否成對
,相對方向的南北/東西可以互消。
宣告stack陣列
負責存放結果以及一pair物件
定義4個屬性NORTH
SOUTH
WEST
EAST
一一遍歷arr
中的方位,若stack
為空則放入arr[i]
,反之判斷stack
最尾端的元素是否與arr[i]
為相對方位,若是則移除stack
最尾端元素,反之stack
放入arr[i]
。
function dirReduc(arr) {
var str = arr.join(''), pattern = /NORTHSOUTH|EASTWEST|SOUTHNORTH|WESTEAST/;
while (pattern.test(str)) str = str.replace(pattern,'');
return str.match(/(NORTH|SOUTH|EAST|WEST)/g)||[];
}
出乎意料的解法!
將arr合併成一字串,使用RegExp檢測是否有符合的字串片段出現,若有就取代成空字串,最後使用match()
回傳符合pattern的陣列。
/NORTHSOUTH|EASTWEST|SOUTHNORTH|WESTEAST/
有符合其中一種字串即可pattern.test(str)
為檢測str是否有匹配pattern,回傳true/falsestr.match(regexp)
,且flag為global的話,會以陣列
方式回傳在str中有match到結果整理可使用正規表示式的Method以及正規表示式物件本身的Method
語法:regexp.exec(str)
exec()
會搜尋str
是否有符合的特定字串,回傳結果陣列
或是null
若沒有使用g
flag,regexp.exec(str)
會回傳第一個匹配的結果,效果如同str.match(regexp)
(沒有g
即代表regexp.lastIndex
被設為0
)
若有使用g
flag:
regexp.exec(str)
會回傳第一個匹配結果,並且以regexp.lastIndex
屬性來儲存下一次執行exec()
要開始搜尋的位置lastIndex
繼續往下搜尋,持續更新regexp.lastIndex
regexp.exec()
本身會回傳null
,並將regexp.lastIndex
設為0
,代表regexp
不繼續搜尋了。let str = 'More about JavaScript at https://javascript.info';
let regexp = /javascript/ig;
let result;
while (result = regexp.exec(str)) {
alert( `Found ${result[0]} at position ${result.index}, ${regexp.lastIndex}` );
// Found JavaScript at position 11,21 then
// Found javascript at position 33,43
}
利用regexp
的lastIndex
屬性,可以指定開始搜尋的位置
let str = 'Hello, world!';
let regexp = /\w+/g; // without flag "g", lastIndex property is ignored
regexp.lastIndex = 5; // search from 5th position (from the comma)
alert( regexp.exec(str) ); // world
語法:regexp.test(str)
test()
會搜尋str
,根據有無符合結果,回傳true/false
範例:
let str = "I love JavaScript";
alert( /love/i.test(str) ); // true
語法:str.match(regexp)
搜尋str
是否有和regexp
匹配的結果
有三種模式(?):
regexp
沒有g
flag,會回傳第一個
匹配到的結果,並以陣列回傳capturing groups
、index
(即match到的位置)、input
(即str
自己))let str = "I love JavaScript";
let result = str.match(/Java(Script)/);
alert( result[0] ); // JavaScript (full match)
alert( result[1] ); // Script (first capturing group)
alert( result.length ); // 2
result內容如下:
regexp
有g
flag,會以陣列方式回傳所有匹配的字串結果capturing groups
和其他的detail)let str = "I love JavaScript";
let result = str.match(/Java(Script)/g);
alert( result[0] ); // JavaScript
alert( result.length ); // 1
result內容如下:
null
回傳null
回傳null
,不是空陣列
沒有注意到,容易產生以下的錯誤:
let str = "I love JavaScript";
let result = str.match(/HTML/);
alert(result); // null
alert(result.length); // Error: Cannot read property 'length' of null
如果希望result要是陣列,可以寫成:
let result = str.match(regexp) || [];
語法:str.search(regexp)
回傳第一個匹配
到的位置,如果沒有符合的則回傳-1
(只會找第一個符合的!)
let str = "A drop of ink may make a million think";
alert( str.search( /ink/i ) ); // 10 (first match position)
語法:str.replace(str|regexp,str|func)
最最最常見的用法,既能搜尋也能做到替換!
在不使用regexp
做替換:
// replace a dash by a colon
alert('12-34-56'.replace("-", ":")) // 12:34-56
只有第一個-
被做到替換,為了能替換掉所有-
,可以用正規表示式/-/g
// replace all dashes by a colon
alert( '12-34-56'.replace( /-/g, ":" ) ) // 12:34:56
在先前Vowel Count,Who likes it?有提到replace()
基本用法
Create Phone Number則是提到replace()
匹配群組的替換。
語法:str.split(regexp|substr,limit)
split()
是分割字串用,可以用substr
字串或是regexp
當作分割或是分界。
// 用中線- 分割字串
alert('12-34-56'.split('-')) // array of [12,34,56]
// 用逗號和空白字元 分割字串
alert('12, 34, 56'.split(/,\s*/)) // array of [12,34,56]
以上內容及範例摘自:
Javascript.info-Methods of RegExp and String
MDN web docs-Regular expressions
以上為今日分享的內容,若有錯誤或是建議,請再隨時和我聯繫。