题目
- 示例1
let str1 ='A3B';
formatString(str1)
// ==> 输出 {A:3,B:1}
- 示例2
let str2='A3(C2)2D';
formatString(str2)
// ==> 输出 {A:3,C:4,D:1}
- 示例3
let str2='(C2)25D(A(R)4B)301R5(E5A(D(B)2)4)4ACB25G';
formatString(str2)
// ==> 输出{ A: 306, C: 51, B: 358, G: 1, R: 1209, E: 20, D: 17 }
字母后面默认为
1可以不写 如str ='A3B1C2D1'==>str ='A3BC2D'
题目分析
字符串
(C2)25D(A(R)4B)301R5(E5A(D(B)2)4)4ACB25G里面包含多层括号,需要里面的括号展开,需要括号里面的内容乘以后面带的倍数
伪代码
- 先展开第一层括号,设计中间量
let $1_ =C2 ,$2_=A(R)4B ,$3_=E5A(D(B)2)4;
//str 可以转换为
let str = $1_*25+$2*301+$3*4+DR5ACB25G;
- 先处理不用再展开的部分
let $_0=DR5ACB25G === 》{D:1,R:5,A:1,C:1,B:25,G:1}
- 处理
C2,A(R)4B,E5A(D(B)2)4因C2,A(R)4B,E5A(D(B)2)4格式相同 可以使用递归的方案的除去多层括号 每次只匹配第一层空号,在字符串没有括号的时候跳出递归
// c2
C2 ==> {C:2}
//A(R)4B
let $_R =R $_0= 4*$_R+4BA ==>{B:4,A:1}
//`E5A(D(B)2)4`
let $_R =(D(B)2) $_1= 4*$_R+E5A ==>{E:5,A:1}
- 递归调用第(一)(二)(三)
- 把所有的结果进行合并
(注意:值合并和key合并两个步骤)
光标标记介绍
假设我们有一个复杂的嵌套列表 ,
(a ((b) (c(d)) e)),
我们在字符串上有一个光标,并且,
从头开始-在第一个(和count = 0之前,然后将光标移到末尾。,
每次光标遇到(时,增加计数。,
每次光标遇到)时,递减计数。,
当count === 0匹配的)时。,
在此示例中,在光标从头到尾移动期间,计数变为,
0 1 2 3 2 3 4 3 2 1 0
通过相同的对光标 我们就可以找配对的()了
获取字符串空号中内容和倍数
function _getBracket(matchString, n) {
let match_array = matchString.split(""),
count = 0,
results = [],
substrArray = [];
//顺序循环取出 括号
for (let i = 0; i < match_array.length; i++) {
const element = match_array[i];
if (element == "(") {
count = count + 1;
count == 1 &&
results.push({
index: i,
content: element,
cursor: count,
});
}
if (element == ")") {
count == 1 &&
results.push({
index: i,
content: element,
cursor: count,
});
count = count - 1;
}
}
// 取出括号和括号内容
for (let m = 0; m < results.length; m = m + 2) {
const start = results[m],
end = results[m + 1],
substring_ = matchString.substring(start.index + 1, end.index);
RegExpString = _replaceAll(_replaceAll(substring_, "(", "\\("), ")", "\\)");
match_substring_array = _getNum(RegExpString, matchString);
substrArray.push({
all: match_substring_array[0],
sub: substring_,
n: Number(match_substring_array[2]) * n,
});
}
return substrArray;
}
获取换元的倍数
function _getNum(substring, matchString) {
RegExpString = "(\\(" + substring + "\\))(\\d*)";
(reg = new RegExp(RegExpString, "g")), (results = []);
matchString.replace(reg, (...arg) => {
results = arg;
});
return results;
}
nodeJs版本下不支持replaceAll方法(自定定义此方法)
function _escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function _replaceAll(str, match, replacement) {
return str.replace(new RegExp(_escapeRegExp(match), "g"), () => replacement);
}
正则陪单个元素和倍数
function _get(remainString, n) {
const reg = /([a-zA-Z])(\d*)/g;
let results = {};
remainString.replace(reg, (...arg) => {
let key = arg[1],
vaule = arg[2] ? Number(arg[2]) : 1;
if (results[key]) {
results[key] = results[key] + vaule * n;
} else {
results[key] = vaule * n;
}
});
return results;
}
合并最后结果(包括值和key)
function _getAll(arr) {
let keys_map_array = [],
keys = [],
results = {};
for (let m = 0; m < arr.length; m++) {
keys_map_array = [...keys_map_array, ...Object.keys(arr[m])];
}
keys = [...new Set(keys_map_array)];
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
for (let j = 0; j < arr.length; j++) {
results[key] = (results[key] || 0) + (arr[j][key] || 0);
}
}
return results;
}
formatString 函数
function formatString(targetString, n = 1) {
const reg = /\((.+)\)(\d+)/g;
let remain_results = {},
bracket_results = {};
//处理没有空号包含部分
let matchString = targetString.match(reg),
remainString = targetString.replace(matchString, "");
if (remainString) {
remain_results = _get(remainString, n);
}
//筛选外层空号包含内容
if (matchString && matchString.length > 0) {
let _bracket = _getBracket(matchString[0], n),
_str = matchString[0],
bracket_remain_results = {},
deep_results = [];
for (let m = 0; m < _bracket.length; m++) {
const item = _bracket[m];
_str = _str.replace(item.all, "");
//子字符串剩余计算
if (item.sub.indexOf("(") > -1 && item.sub.indexOf(")") > -1) {
deep_results.push(formatString(item.sub, item.n));
} else {
deep_results.push(_get(item.sub, item.n));
}
}
//处理子字符串 不含括号
if (_str && _str.length > 0) {
bracket_remain_results = _get(_str, n);
}
bracket_results = _getAll([...deep_results, bracket_remain_results]);
}
return _getAll([remain_results, bracket_results]);
}