昨天面試中,面試官問了一個用replace結合正則實現清除字符串兩邊空格的方法,這個還是很好實現的,網上也有很多記錄,基本上都是匹配字符串兩側的空白符,替換為空字符就可以了。
大體上就是下面這種方法。
String.prototype.trim = function(){
return this.replace(/^(\s*)|(\s*)$/g, '');
}
而后面試官提了個進階要求,保留兩側的空格,而清除內部的空格。
這個要求一開始覺得也沒什么難度,但是寫了好一會兒也沒寫出來。之后面試官給我講解思路寫了一個,可以肯定這是隨性出的題。因為他也沒寫好(:joy:)。
當時寫出來的是下面這樣的方法
' aa bbb cc '.replace(/(\S)\s+(\S)/g,'$1$2'); // " aabbbcc "
本以為是很OK的,結果出BUG了。
當改變了字符串之后:
' aa a bbb cc '.replace(/(\S)\s+(\S)/g,'$1$2'); // " aaa bbbcc "
很顯然與預期並不相同,其原因就是匹配的后面一個非空字符在匹配一次后,會將指針向下一個索引移動,從而導致的問題就是如果中間某個非空字符只有一位,那么它后面的空白符就沒辦法匹配到了,因為此時繼續匹配的話,開頭匹配的非空字符就要從該非空字符的下一個開始匹配了,這兩個非空字符之間的空白符就無法清除。
(其實當時討論的時候只是提到了正則匹配到的后面一個非空字符不會參與下次匹配,並沒有說這么詳細,這是我之后想到的。)
因為處於面試中,當時並沒有糾結於這一個問題。但是回來之后自己又試了一些方法,最后終於找到了一種匹配的正則。
' a aaa bbb b c cc ccc '.replace(/(\S)\s+(\b)/g,'$1$2'); // " aaaabbbbcccccc "
改變的其實並不多,只是將后面的一個\S改成了\b。其實就是針對最后一個非空字符匹配之后索引后移的問題,將最后匹配的改成一個非實體的邊界符就OK了,這么想起來真是有點哭笑不得。
說起來今天跟人說我的號碼的時候,本來很熟練的一串數字,說了兩個突然卡殼了,然后想了好幾秒才回想起來自己的電話號碼,這還能說些什么呢。。。 :joy:
不管怎樣,先記下來吧。