C#正規表示解析/擷取/取代字串 Regex.Replace
這是幾個月前CodeFight時遇到的情境,最近才想到可以用正規表示處理
題目出處 Arcade > Intro > 13 reverseInParentheses
給定一個只包含小寫英文字母以及括號的字串,該字串括號必定成對出現(well-formed),寫一個method將所有括號內的字串反轉並回傳
ex:
reverseInParentheses(inputString) = "foobazrabblim"
因為 "foo(bar(baz))blim" => "foo(barzab)blim" => "foobazrabblim"
最初看到這個問題時是用迴圈+stack去解析成對的括號,做是做出來了,只是code較為複雜
string reverseInParentheses(string inputString) {
Stack<char> st = new Stack<char>();
foreach(var ch in inputString)
{
if(ch == ')')
{
List<char> tempList = new List<char>();
while(st.Any())
{
char p = st.Pop();
if(p == '(')
{
break;
}
tempList.Add(p);
}
tempList.ForEach(x => st.Push(x));
}
else
{
st.Push(ch);
}
}
return string.Join("", st.Reverse());
}
最近終於改寫了一個使用正規表示的方法,看起來精簡些了,使用了正規表示+遞迴
先擷取出括號的字串,將其反轉後取代原字串,反覆執行直到整個字串都處理完畢,\w的匹配為[A-Za-z0-9_],每次匹配時只對配到括號內包含[A-Za-z0-9_]的,至於括號包括號的則等到下一輪處理
string reverseInParentheses(string inputString) {
var pattern = @"\((?<reverseStr>\w*)\)";
if(!Regex.Match(inputString, pattern).Success)
return inputString;
return reverseInParentheses(
Regex.Replace(inputString, pattern,
x => string.Concat(x.Groups["reverseStr"].Value.Reverse())
));
}
正規表示中括號代表match括號內的任一字元;小括號代表match括號內的整個pattern,並且將結果存至一個變數中。如果搞錯小括號與中括號的意義就不能如預期擷取了
小括號匹配的pattern還可以取個名字
注意到語法中的 \( 與 \) 是放在小括號的外面的,因此擷取到的部分(reverseStr)已經沒有括號,直接反轉後取代就可以了
LinqPad可以看到Groups的Value部分
參考: