合拾

关于一道字符串格式化面试题的思考

2018-11-16


本文从一道简单的字符串面试题开始,记录字符串的一些方法,关注细节。

image

最近遇到一道面试题,觉得挺有意思,虽然简单缺发人深省。题目大致如下:写一个字符串转成驼峰的方法,例:border.bottom.color->borderBottomColor。

操作字符串数组

大部分人应该都能写出这种方法,对字符串进行处理然后拼接成新的字符串。主要考察字符串的几个 API,使用 charAt(n)来取得字符串第 n 个下标的字符,也可以使用数组下标([])来取。

function tranformStr(str) {
var strArr = str.split(".");
for (var i = 1; i < strArr.length; i++) {
strArr[i] = strArr[i].charAt(0).toUpperCase() + strArr[i].substring(1);
}
return strArr.join("");
}

正则表达式

第二种使用正则来解决,其实算是字符串的 replace 方法和正则的结合,难点主要还是在于 replace 方法的掌握。

function transformStr(str) {
var re = /\.(\w)/g;
return str.replace(re, function(match, p1) {
return p1.toUpperCase();
});
}

从以上两种方法可以看出,使用正则的代码量更少,但是对正则的理解和 replace 用法的要求也更高,下面总结一下 replace 这个字符串方法的一些 api。

replace 使用

str.replace(regexp|substr, newSubStr|function)

replace 方法的第一个参数可以是一个正则或者字符串。

  • regexp (pattern)

一个正则表达式(RegExp) 对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。

  • substr (pattern)

一个要被 newSubStr 替换的字符串。其被视为一整个字符串,而不是一个正则表达式。仅仅是第一个匹配会被替换。

replace 方法的第二个参数可以是一个字符串或者函数。

  • newSubStr (replacement)

用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。参考下面的使用字符串作为参数。

  • function (replacement)

一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的指定一个函数作为参数。

replace 方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。
在进行全局的搜索替换时,正则表达式需包含 g 标志。

使用字符串作为参数

当第二个参数是字符串时,替换字符串可以插入下面的特殊变量名:

变量名 代表的值
\$\$ 插入一个 “\$”。
\$& 插入匹配的子串。
\$` 插入当前匹配的子串左边的内容。
\$’ 插入当前匹配的子串右边的内容。
\$n 假如第一个参数是 RegExp 对象,并且 n 是个小于 100 的非负整数,那么插入第 n 个括号匹配的字符串。

下面是特殊变量名的具体使用:

"border.bottom.color".replace(/\.(\w)/g, "$$");
// border$ottom$olor
"border.bottom.color".replace(/\.(\w)/g, "$&");
// border.bottom.color
"border.bottom.color".replace(/\.(\w)/g, "$`");
// borderborderottomborder.bottomolor
"border.bottom.color".replace(/\.(\w)/g, "$1");
// borderbottomcolor

指定一个函数作为参数

当第二个参数是一个函数时,在这种情况下,当匹配执行后, 该函数就会执行。 函数的返回值作为替换字符串。 (注意: 上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是, 如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么这个方法将被多次调用, 每次匹配都会被调用。

变量名 代表的值
match 匹配的子串。(对应于上述的\$&。)
p1,p2, … 假如 replace()方法的第一个参数是一个 RegExp 对象,则代表第 n 个括号匹配的字符串。(对应于上述的$1,$2 等。)
offset 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是“abcd”,匹配到的子字符串是“bc”,那么这个参数将是 1)
string 被匹配的原字符串。

注意:精确的参数个数依赖于 replace()的第一个参数是否是一个正则表达式对象, 以及这个正则表达式中指定了多少个括号子串。

在文章最开始的题目中,我们需要匹配.后面跟着的第一个字母,并且将其替换为大写字母。具体实现代码如下:

function transformStr(str) {
var re = /\.(\w)/g;
return str.replace(re, function(match, p1) {
return p1.toUpperCase();
});
}

首先,声明一个正则 re,匹配一个.后面跟着一个括号,这个括号称为捕获括号,匹配的内容会被记住以供第二个参数使用,捕获括号内的\w 匹配一个单字字符(字母、数字或者下划线),等价于[A-Za-z0-9]。第二个参数为函数,第一个字符串 match 是每次匹配到的字符串,在上述例子中就是.b 和.c,p1 则对应第一个括号匹配的字符串,对应 b 和 c,在函数内部对 p1 进行大写转换,因为 replace 产生的是一个全新的字符串,所以需要 return 出去。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章