# 字符串类高频面试题

# 1.parseFloat,parseInt

  • https://juejin.im/post/5dbff8735188252ddb2fd25e
  • ['1', '2', '3'].map(parseInt)的输出结果是什么?['1', '2', '3'].fliter(parseInt)的输出结果是什么?
['1', '2', '3'].map(parseInt)
// [1, NaN, NaN]
['1', '2', '3'].map(parseFloat)
// [1, 2, 3]
['1', '2', '3'].filter(parseInt)
// ["1"]
['1', '2', '3'].filter(parseFloat)
// ["1", "2", "3"]
  • 一个小的知识点:如何快速将一个字符串数组转化为数字类型的数组
['1', '2', '3'].map(parseFloat)
['1', '2', '3'].map(Number)

# 2.解析 URL Params 为对象

let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';

/* 结果
{ 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)) { // 处理有 value 的参数
      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;
}

//将url对象解析为参数字符串
let params = new URLSearchParams(search)
console.log(params)
console.log(params.toString()) 

# 3.模板引擎实现

render(template, data); // 我是姓名,年龄18,性别男

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
  name: '张三',
  age: 18,
  sex: '男'
}

function render(template, data){
  let reg = /\{\{(\w+)\}\}/g  // 模板字符串正则
  const ret = template.replace(reg, (match, $1)=>{
    console.log(match,$1)
    return data[$1]
  })
  return ret
}

# 4.转化为驼峰命名

var s1 = "get-element-by-id",转化为驼峰命名

function translate(s){
  let reg = /-(\w)/g
  let ret = s1.replace(reg, (match, $1) => {
    console.log(match,$1)
    return $1.toUpperCase()
  })
  return ret
}

function translate(s1){
  let reg = /-(\w)/g
  let s = s1.slice(0,1).toUpperCase()
  let s2 = s1.slice(1).replace(reg, (match, $1) => {
    console.log(match,$1)
    return $1.toUpperCase()
  })
  return s.concat(s2)
}

# 4.查找字符串中出现最多的字符和个数 ???

  • 例: abbcccddddd -> 字符最多的是d,出现了5次
let str = "abcabcabcbbccccc";
let num = 0;
let char = '';

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

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

# 5.字符串查找

  • 请使用最基本的遍历来实现判断字符串 a 是否被包含在字符串 b 中,并返回第一次出现的位置(找不到返回 -1)
  • 对一个整数连续两次二进制否运算,得到它自身
  • 所有的位运算都只对整数有效。二进制否运算遇到小数时,也会将小数部分舍去,只保留整数部分。所以,对一个小数连续进行两次二进制否运算,能达到取整效果
~~3 // 3
~~2.9 // 2
~~47.11 // 47
~~1.9999 // 1

a='34';b='1234567'; // 返回 2
a='35';b='1234567'; // 返回 -1
a='355';b='12354355'; // 返回 5
isContain(a,b);
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;
}

# 6.实现千位分隔符

// 保留三位小数
parseToMoney(1234.56); // return '1,234.56'
parseToMoney(123456789); // return '123,456,789'
parseToMoney(1087654.321); // return '1,087,654.321'
function parseToMoney(num) {
  num = parseFloat(num.toFixed(3));
  let [integer, decimal] = String.prototype.split.call(num, '.');
  integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,');
  return integer + '.' + (decimal ? decimal : '');
}
// 正则表达式(运用了正则的前向声明和反前向声明):
function parseToMoney(str){
   // 仅仅对位置进行匹配
   let re = /(?=(?!\b)(\d{3})+$)/g; 
   return str.replace(re,','); 
}

# 7.判断是否是电话号码

function isPhone(tel) {
    var regx = /^1[34578]\d{9}$/;
    return regx.test(tel);
}

# 8.验证是否是邮箱

function isEmail(email) {
    var regx = /^([a-zA-Z0-9_\-])+@([a-zA-Z0-9_\-])+(\.[a-zA-Z0-9_\-])+$/;
    return regx.test(email);
}

# 9.验证是否是身份证

function isCardNo(number) {
    var regx = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return regx.test(number);
}

# 10.判断一个单词是否是回文?

function checkPalindrome(str){
  return str === str.split('').reverse().join('');
}