【问题标题】:Regex — Match Range but only once per unique character正则表达式 - 匹配范围,但每个唯一字符仅匹配一次
【发布时间】:2017-03-13 00:43:47
【问题描述】:

我试图通过使用正则表达式范围来避免数组和循环,但是,我只想替换范围内每个字符的第一个实例一次。

我正在使用范围,因为我无法保证订购,也无法重新订购。

例如:

"access".replace(/[access]/g, '') = "cs", instead of "". "cell phones".replace(/[el]/g) = "cl phones", instead of "c phons"

无论如何,正则表达式范围内的双精度都是多余的,在这种情况下,它也不应该导致第二次出现被替换。

如果这是不可能的,那我就得想点别的了。

【问题讨论】:

  • 您可以缓存删除的字符并防止进一步删除,替换的第二个参数将是一个函数!

标签: javascript regex regex-lookarounds


【解决方案1】:

这需要向后看 - 看看字符是否更早出现并因此应该保留。但是 JS 不支持。搜索“JS look-behind regexp”以获得一些想法。经典的方法是反转字符串,以便您可以使用前瞻:

const rev = s => s.split('').reverse().join('');

const testData = [
  ["access", 'access'],
  ["cell phones", 'el']
];

function match(s, chrs) {
  const reg = new RegExp(`([${chrs}])(?!.*\\1)`, "g");
  return rev(rev(s).replace(reg, ''));
}
  
testData.forEach(([input, chrs]) => console.log("input", input, "gives", match(input, chrs)));

【讨论】:

    【解决方案2】:

    作为我在上面评论中所说的一个例子:

    function replace(str, regex) {
      var cache = {};          // the cache object
      return str.replace(regex, function(m) {
        if(cache[m]) return m; // if we already removed an instance of this matched character then don't remove any further instances
        
        // otherwise ...
        cache[m] = true;       // cache the character
        return '';             // remove it
      });
    }
    
    console.log('"access", /[access]/g => ', replace("access", /[access]/g));
    console.log('"cell phones", /[el]/g => ', replace("cell phones", /[el]/g));

    注意:假设传递的正则表达式都只是字符集(你称之为范围),只允许/[...]/g,否则行为将不是你想要的。

    【讨论】:

      【解决方案3】:

      “记住”逻辑的单行版本。

      "cell phones".replace(/[el]/g, (() => { let seen = []; return m => seen.includes(m) ? m : (seen.push(m),''); })())
      

      更短的版本:

      "cell phones".replace(/[el]/g, (seen => m => m in seen ? m : seen[m] = ''))({}))
      

      【讨论】:

      • 整个 jQuery 库是一个单行... 而是让你的代码可读
      • 如果你想写短代码,为什么不用箭头函数的简洁体形式呢?单个参数也不需要括号。所以a => b 而不是(a) => { return b; }
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-15
      相关资源
      最近更新 更多