banner
他山之石

他山之石

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


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

image

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

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。