字符串处理(递归、正则、String,光标标记等综合应用)

153 阅读1分钟

题目

  • 示例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)4C2, 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]);
}

运行结果

1655283678303.jpg