分享几道经典的字符串面试题
解析 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