昨天面试中,面试官问了一个用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:
不管怎样,先记下来吧。