微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正则表达式/Javascript,用绝对值转换字符串|x|到 abs(x)

如何解决正则表达式/Javascript,用绝对值转换字符串|x|到 abs(x)


我正在尝试使用 Javascript 中的正则表达式转换一些包含绝对值的数学相关字符串。 我想将所有出现的 |foo| 转换为 abs(foo)

鉴于它们也可以嵌套,我如何检测字符是打开还是关闭? 基本上,我想将所有出现的打开 | 转换为 abs(,并将所有关闭 | 转换为 )。竖线之间的任何内容都保持不变。

一些可能的输入和期望的输出示例:
|x|+12
abs(x)+12

|x|+12+|x+2|
abs(x)+12+abs(x+2)

|x|+|x+|z||
abs(x)+abs(x+abs(z))

有什么想法吗?

解决方法

有支持嵌套的正则表达式方言,JavaScript 不是其中之一。但是,您可以分步执行此操作:

  1. 用嵌套级别(+1、-1,从左到右)标记 |
  2. 根据标签从左到右,从最低级到最高级识别同一级别的开始和结束|
  3. 在输入不平衡的情况下清理剩余的标签

具有多达 3 个级别的测试用例的功能代码(代码适用于任何级别):

function fixAbs(str) {
  const startTag = '{{s%L%}}';
  const endTag   = '{{e%L%}}';
  const absRegex = /\{\{s(\d+)\}\}(.*?)\{\{e\1\}\}/g;
  let level = 0;
  str = str
  .replace(/ /g,'')  // remove all spaces
  .replace(/(\|*)?(\w+)(\|*)?/g,function(m,c1,c2,c3) {
    // regex matches variables with all leading and trailing `|`s
    let s = c2;
    if(c1) {
      // add a start tag to each leading `|`: `{{s0}}`,`{{s1}}`,...
      // and post-increase level
      s = '';
      for(let i = 0; i < c1.length; i++) {
        s += startTag.replace(/%L%/,level++);
      }
      s += c2;
    }
    if(c3) {
      // decrease level,// and add a end tag to each trailing `|`: `{{e2}}`,`{{e1}}`,...
      for(let i = 0; i < c3.length; i++) {
        s += endTag.replace(/%L%/,--level);
      }
    }
    return s;
  });
  // find matching start and end tag from left to right,// repeat for each level
  while(str.match(absRegex)) {
    str = str.replace(absRegex,c3) {
      return 'abs(' + c2 + ')';
    });
  }
  // clean up tags in case of unbalanced input
  str = str.replace(/\{\{[se]-?\d+\}\}/g,'|'); 
  return str;
}

const testCases = [
  '|x|+12','|x|+|y+|z||','|x|+||y|+z|','|x|+|x+|y|+z|','|x|+|x+|y+|t||+z|','|x|+12+|2+x|','|x|+12+|x+2|'
].forEach(str => {
  let result = fixAbs(str);
  console.log('"' + str + '" ==> "' + result + '"');
});

输出:

"|x|+12" ==> "abs(x)+12"
"|x|+|y+|z||" ==> "abs(x)+abs(y+abs(z))"
"|x|+||y|+z|" ==> "abs(x)+abs(abs(y)+z)"
"|x|+|x+|y|+z|" ==> "abs(x)+abs(x+abs(y)+z)"
"|x|+|x+|y+|t||+z|" ==> "abs(x)+abs(x+abs(y+abs(t))+z)"
"|x|+12+|2+x|" ==> "abs(x)+12+abs(2+x)"
"|x|+12+|x+2|" ==> "abs(x)+12+abs(x+2)"

为了清晰起见,代码用注释进行了注释。

这是基于位于 https://twiki.org/cgi-bin/view/Blog/BlogEntry201109x3

的 TWiki 博客

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。