正则表达式——匹配范围,但每个唯一字符只匹配一次
Regex — Match Range but only once per unique character
我试图通过使用正则表达式范围来避免数组和循环,但是,我只想替换范围内每个字符的第一个实例一次。
我使用范围是因为我不能保证顺序并且不能重新排序。
例如:
"access".replace(/[access]/g, '') = "cs", instead of "".
"cell phones".replace(/[el]/g) = "cl phones", instead of "c phons"
正则表达式范围内的双打无论如何都是多余的,在这种情况下,它也不应该导致第二次出现被替换。
如果这不可能,那我就得想别的办法了。
这需要向后看 -- 查看该字符是否更早出现并因此应保留。但是 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)));
以我在上面评论中所说的为例:
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));
注意:假设传递的正则表达式都是字符集(ranges as you call them),只允许/[...]/g
,否则行为获胜随心所欲
"remembering" 逻辑的单行版本。
"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] = ''))({}))
我试图通过使用正则表达式范围来避免数组和循环,但是,我只想替换范围内每个字符的第一个实例一次。
我使用范围是因为我不能保证顺序并且不能重新排序。
例如:
"access".replace(/[access]/g, '') = "cs", instead of "".
"cell phones".replace(/[el]/g) = "cl phones", instead of "c phons"
正则表达式范围内的双打无论如何都是多余的,在这种情况下,它也不应该导致第二次出现被替换。
如果这不可能,那我就得想别的办法了。
这需要向后看 -- 查看该字符是否更早出现并因此应保留。但是 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)));
以我在上面评论中所说的为例:
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));
注意:假设传递的正则表达式都是字符集(ranges as you call them),只允许/[...]/g
,否则行为获胜随心所欲
"remembering" 逻辑的单行版本。
"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] = ''))({}))