字符串--常见面试题

194 阅读2分钟
解析 URL Params 为对象

举个例子

    let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
    parseParam(url);
    // {
    //   user: 'anonymous',
    //   id: [123,456], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
    //   city: '北京', // 中⽂需解码
    //   enabled: true, // 未指定值得 key 约定为 true
    // }


    function parseParam(url){
      const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将?后面的字符串取出来
      const paramsArr = paramsStr.split('&'); // 将字符串以&分割后存到数组中
      let paramsObj = {};
      // 将params存到对象中
      paramsArr.forEach(param => {
        if(/=/.test(param)){
          let [key,val] = param.split('='); // 分割key和value
          val = decodeURIComponent(val); // 解码
          val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字

          if(paramsObj.hasOwnProperty(key)){ // 如果对象有key,则添加一个值
            paramsObj[key] = [].concat(paramsObj[key],val);
          }else{ // 如果对象没有这个key,创建key并设置值
            paramsObj[key] = val;
          }
        }else{ // 处理没有value的参数
          paramsObj[param] = true;
        }
      });
      return paramsObj;
    }
模版引擎实现

vue中用到的{{xxx}}这样的语法,被{{ xxx }}包含的就是我们要替换的变量。我们怎么把数据导入到模板里面呢??我们会想到的就是采用的是正则匹配,用replace直接替换里面的变量。具体实现如下:

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
    name: '姓名',
    age: 18
}
render(template,data); // 我是姓名,年龄18,性别undefined

function render(template,data){
    const reg = /\{\{(\w+)\}\}/; 模版字符串正则
    if(reg.test(template)){ // 判断模版里是否有模版字符串
        const name = reg.exec(template)[1]; // 查找当前模版里第一个模版字符串的字段
        template = template.replace(reg,data[name]); // 将第一个模版字符串渲染
        return render(template,data); // 递归的渲染并返回渲染后的结构
    }
    return template; // 如果模版没有模版字符串直接返回
}
转化为驼峰命名

这里采用的是正则匹配,然后replace替换,slice截取,找到对应的字符串,用 toUpperCase 方法转换为大写。具体实现如下:

var s1 = 'get-element-by-id';

var f = function (s) {
    return s.replace(/-\w/g,function(x){
        return x.slice(1).toUpperCase();
    })
}
查找字符串中出现最多的字符和个数

例: abbcccddddd -> 字符最多的是d,出现了5次

先将其转换成数组,再做次排序,最后转成字符串。这样相同字符的排到了一起。接着,创建两个变量,分别用来记录出现的字符和它出现的次数。判断出现多的次数,替换小于它的频次。具体实现看下面:

let str = "abcabcabcbbccccc";
let num = 0;
let char = '';

// 使其按照一定的次序排列
str = str.split('').sort().join('');
// abcabcabcbbccccc

// 定义正则表达式
let re = /(\w)\1+/g;
str.replace(re,(x,y) => {
    if(num < x.length){
        num = x.length;
        char = y;
    }
})
console.log(`字符串最多的是${char},出现了${num}次`)

字符串查找

question:请使⽤最基本的遍历来实现判断字符串 a 是否被包含在字符串 b 中,并返回第⼀次出现的位置(找不到返回 -1)。

首先,循环这个被查找的字符串b,设置它的初始状态为true,循环待查找的字符串a。若没有任何匹配到的,设置状态为false,返回-1,即找不到。若循环结束,初始状态仍未变,还是true,则返回当前循环的b字符串当前的i(位置)。具体实现如下:

function isContain (a,b) {
  for(let i in b){
    if(a[0] === b[i]){
      let tmp = true;
      for(let j in a){
        if(a[j] !== b[~~i + ~~j]){
          tmp = false;
        }
      }
      if(tmp){
        return i;
      }
    }
  }
  return -1;
}

a='34';b='1234567'; // 返回 2 
a='35';b='1234567'; // 返回 -1 
a='355';b='12354355'; // 返回 5
isContain(a,b);

实现千位分割符
  • 将这个数四舍五入,保留3位小数,并返回浮点数。
  • 通过小数点分割。
  • 将小数点前的数正则匹配,3位添加逗号
  • 将小数点前后处理过的数拼接好,返回

具体实现如下:

function parseToMoney(num){
    num = parseFloat(num.toFixed(3)); // 四舍五入,保留3位小数,并返回浮点数
    let [integer,decimal] = String.prototype.split.call(num, '.');
    integer = integer.replace(/\d(?=(\d{3})+$)/g,'$&,');
    return integer + '.' + (decimal ? decimal : '');
}

// 保留三位⼩数 
parseToMoney(1234.56); // return '1,234.56' 
parseToMoney(123456789); // return '123,456,789' parseToMoney(1087654.321); // return '1,087,654.321'

判断是否是电话号码
function isPhone(tel){
    var regx = /^1[34578]\d{9}$/;
    return regx.test(tel);
}
验证是否是邮箱
function isEmail(email){
    var regx = /^([a-zA-Z0-9_\-])+@([a-zA-Z0-9_\-])+(\.[a-zA-Z0-9_\-])+$/;
    return regx.test(email);
}
验证是否是身份证
function isCardNo(number){
    var regx = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return regx.test(number);
}
大小写互转

例如 'AbcD' ==> 'aBCd'

// 方法一
const processStr = (str) => {
  const arr = str.split('');
  const _arr = arr.map(vl => {
    return vl === vl.toUpperCase() ? vl.toLowerCase() : vl.toUpperCase();
  });
  return _arr.join('');
}
// 方法二
const swapStr = (str) => {
  let result = '';
  for(let i=0;i<str.length;i++){
    let item = str[i];
    if(item === item.toUpperCase()){
      result += item.toLowerCase();
    }else{
      result += item.toUpperCase();
    }
  }
  return result;
}
// console.log(swapStr('ADcijgDBkkbB@#&()'))
在输入框中如何判断输入的是一个正确的网址
function isUrl(url) {
  const a = document.createElement("a");
  a.href = url;
  return (
    [/^(http|https):$/.test(a.protocol),a.host,a.pathname !== url,a.pathname !== `/${url}`].find(x => !x) === undefined
  );
}