【面试宝典】字符串类高频面试题

316 阅读1分钟

分享几道经典的字符串面试题

解析 URL Params 为对象

let url = 'http://www.baidu.com/?user=panfengshan&id=333&id=666&city=%E5%8C%97%E4%BA%AC&readOnly';
parseUrlParam(url)
/* 结果
{ user: 'panfengshan',
  id: [ 333, 666 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
  city: '北京', // 中文需解码
  readOnly: true, // 未指定值得 key 约定为 true
}
*/
function parseUrlParam (url) {
  // 将 ? 后面的字符串取出
  const paramsStr = /.+\?(.+)$/.exec(url)[1];
  // 得到 key=value 数组
  const paramsArr = paramsStr.split('&');
  const params = {};
  paramsArr.forEach(param => {
    let [key, value] = param.split('=');
    if (value) {
      // 解码
      value = decodeURIComponent(value);
      // 能被转成数字的就转成数字类型
      value = /\d+/.test(value) ? parseFloat(value) : value;
      if (params[key]) {
        // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
        params[key] = [].concat(params[key], value);
      } else {
        params[key] = value;
      }
    } else {
      // 未指定值得 key 约定为 true
      params[key] = true;
    }
  });
  return params;
}

模板引擎解析实现

简单实现一下类似于 handlebars 的模板变量解析

const template = '我是{{name}},性别{{gender}},年龄{{age}}';
const renderData = {
  name: '星空',
  gender: '男',
  age: 20
};
render(template, renderData) // 我是星空,性别男,年龄20
function render (template, data) {
  // 模板字符串正则
  const reg = /\{\{(\w+)\}\}/;
  // 存在模板字符串,进行解析替换
  if (reg.test(template)) {
    // 取出模板字符串里面的变量
    const key = reg.exec(template)[1];
    // 替换模板中第一个匹配到的变量为对应的数据
    template = template.replace(reg, data[key]);
    // 递归调用,将模板字符串中的变量全部替换
    return render(template, data);
  }
  return template;
}

驼峰命名【camelCase】

将横线连接的变量转换为驼峰命名 get-elementseby-class-name 转为 getElementsByClassName

function toCamelCase (str) {
  // replace 第二个参数可以是一个方法,参数为匹配到的内容
  return str.replace(/-\w/g, function (s) {
    // 将 - 后的字母转为大写
    return s.slice(1).toUpperCase();
  });
}

查找字符串中出现最多的字符和出现次数

const str = 'abcabcabcbbcccccbbbb';

function getMostStr (str) {
  // 保存字符出现的次数
  const dic = {};
  // 出现次数最多的字符
  let letter = '';
  // 出现次数
  let count = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charAt(i);
    // 字符第一次出现,初始化次数为1
    if (!dic[char]) {
      dic[char] = 1;
    } else {
      // 累加次数
      dic[char]++;
    },
    // 当前字符出现次大于之前最多的字符出现次数,更新 letter、count
    if (dic[char] > count) {
      letter = char;
      count = dic[char];
    }
  }
  return { letter, count };
}

console.log(getMostStr(str)); // {letter: 'b', count: 9}

千分位分隔符

// 保留三位小数
parseToMoney(1234.56); // return '1,234.56'
parseToMoney(123456789); // return '123,456,789'
parseToMoney(1087654.321); // return '1,087,654.321'
function parseToMoney (num) {
  // 保留三位小数,同时通过 parseFloat 去掉小数都是 0 的情况
  num = parseFloat(num.toFixed(3));
  // 获取整数部分、小数部分
  let [integer, decimal] = String.prototype.split.call(num, '.');
  // 对整数部分进行千分位处理
  integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,');
  return integer + (decimal ? '.' + decimal : '');
}

console.log(parseToMoney(123456789)); // 123,456,789
console.log(parseToMoney(4567.1234)); // 4,567.123
console.log(parseToMoney(-4567.1234)); // -4,567.123