假设我有一个函数,看起来是这样的:
function countReplacements ( string, search, replacement ) {
string.replace ( search, replacement );
}知道有多少匹配被替换到字符串中,最干净、最可靠的方法是什么?
我想出了以下可能的解决方案:
replacement值包装在一个代理中,该代理每次访问代理值时都会记录。不过,这并不适用于较早版本的JS。String.prototype.replace中使用的算法,这样每次它替换某个东西时,它都会记录下来。这里一点也不干净。search是字符串或非全局正则表达式,我可以检查string是否包含/匹配它。但是如果search是全局正则表达式,那么当JS支持查找时--我不确定这是否有效--也许所有匹配都是在实际替换它们之前计算出来的?如果不是这种情况,任何替换都可能导致下面的查找后面不再匹配,或者现在匹配它在原始字符串中不匹配的内容。你认为什么是解决这个问题的最好办法?
发布于 2018-10-16 00:11:03
对于替换为字符串的普通情况,对于.replace的第二个参数,使用回调函数而不是普通的replacement字符串,并使回调增量成为一个变量:
function countReplacements(string, search, replacement) {
let count = 0;
const result = string.replace(search, () => {
count++;
return replacement;
});
return { count, result };
}
console.log(countReplacements('foobar', /o/g, 'a'));
对于更复杂的情况,当replacement是一个函数或包含组引用的字符串时,您必须自己重新实现String.prototype.replace:使用提供给.replace的参数来获得完全匹配和组:
function countReplacements(string, search, replacement) {
let count = 0;
const result = string.replace(search, (match, ...groups) => {
count++;
return replacement
.replace(/\$(\d+|&)/g, (_, indicator) => {
if (indicator === '&') return match;
if (/^\d+$/.test(indicator)) return groups[indicator - 1];
// and so on for other `$`s
});
});
return { count, result };
}
console.log(countReplacements ( 'foobar', /(o)/g, '$1_' ));
一个更懒惰但更容易实现的版本就是调用match并检查结果的length,尽管这需要使用正则表达式遍历字符串两次。
function countReplacements(string, search, replacement) {
const match = string.match(search);
const count = match ? match.length : 0;
const result = string.replace(search, replacement);
return { count, result };
}
console.log(countReplacements ( 'foobar', /(o)/g, '$1_' ));
如果搜索是字符串或非全局正则表达式,则可以检查字符串是否包含/匹配。但是如果搜索是一个全局正则表达式,那么当JS将支持查找--我不确定这是否有效--也许所有匹配都是在实际替换它们之前计算出来的?如果不是这种情况,任何替换都可能导致下面的查找后面不再匹配,或者现在匹配它在原始字符串中不匹配的内容。
这不是一个问题--使用.match来获取.replace之外的计数的唯一问题是,它需要遍历字符串两次。字符串的替换都是一次计算的,在这里,旁观者正在查看原始字符串。然后,一旦找到所有匹配项并计算替换值,则每个匹配的子字符串将被替换。
https://stackoverflow.com/questions/52826265
复制相似问题