两个索引之间的多个顺序字符串替换
Posted
技术标签:
【中文标题】两个索引之间的多个顺序字符串替换【英文标题】:Multiple sequential string replacement between two indices 【发布时间】:2015-05-22 05:00:34 【问题描述】:我有一个长字符串 'str' 和一个 [start, end, replace_str] 形式的三元组列表。我需要遍历三元组列表并用 replace_str 替换开始和结束索引之间的 'str' 的内容。 replace_str 字符串可以是可变长度的。问题是在第一个三元组替换之后,“str”的内容和长度发生了变化,并且下一个三元组的开始和结束索引的替换不保持有效,并且替换发生在错误的位置。
例如如果
str = 'I want to go to India.'
三元组的列表是
[3,7,'<span id="7">want</span>']
[11,13,'<span id="49">go</span>']
[1,2,'<span id="1003">I</span>']
用第一个三元组替换后,'str' 看起来像:
'I <span id="7">want</span> to go to India'.
现在用 start = 11 和 end = 13 替换第二个三元组,str 将如下所示:
'I <span id<span id="49">go<span>>7">want</span> to go to India.'
而我希望它看起来像
'I <span id="7">want</span> to <span id="49">go<span> to India.'
如何在 javascript 中处理这样多个连续的字符串替换?
编辑: https://***.com/users/82548/david-thomas 建议我上面的原始问题是 XY 问题 - 另一个问题的解决方案问题而不是实际问题。那么问题就来了。
从:开始
str = 'I want to go to India.'
三元组的列表是
[3,7,'<span id="7">want</span>']
[11,13,'<span id="49">go</span>']
[1,2,'<span id="1003">I</span>']
我想用 replace_str 替换 start 和 end 之间 str 的内容,以便我的结果字符串,替换所有三元组后,将如下所示:
'<span id="1003">I<span> <span id="7">want</span> to <span id="49">go<span> to India.'
【问题讨论】:
我认为这是试图解决另一个问题的问题 - 也称为“XY problem”。您能否告诉我们,或向我们展示最初的问题是什么,因为这个解决方案感觉过于复杂。 我已经在编辑中提供了上述实际问题的描述。 查看(可能是简化的)输入/输出,这似乎是一个关于如何用特定id
的元素包装某些单词的问题?如果提供的词('want'
、'go'
和 'I'
)的所有实例出现不止一次,是否应该替换,或者只替换特定(初始)索引处的实例?
是的。问题是用特定的 id 包装 str 的某些子字符串。它只需要针对指定的索引发生一次。
继续@DavidThomas 的问题:您需要在什么背景下解决这个问题?不同的跨度id
s 代表什么?每个包含“我”的句子都会用<span id="1003">
包裹这个词吗?所有代词都会被包裹在<span id="1003">
中吗?还是只有一个字母的所有单词?你是只给了一个“长字符串'str'”来处理,还是你有很多类似的字符串?你能举个例子吗?您对每个字符串中的相同单词使用的id
s 是否相同?也许有一个更通用的解决方案可以有效地解决这个问题。
【参考方案1】:
假设替换三元组从不重叠,那么您可以从末尾开始,然后从头开始:
String.prototype.replaceBetween = function(start, end, what)
return this.substring(0, start) + what + this.substring(end);
;
var str = 'I want to go to India.'
var triplets = [
[3,7,'<span id="7">want</span>']
, [11,13,'<span id="49">go</span>']
, [1,2,'<span id="1003">I</span>']
]
triplets.sort(function (a, b)
return b[0] - a[0]
)
for (var ii=0, triplet; triplet=triplets[ii]; ii++)
str = str.replaceBetween(triplet[0]-1, triplet[1], triplet[2])
console.log(str)
// <span id="1003">I</span><span id="7">want</span>to <span id="49">go</span>to India.
你可以找到关于replaceBetween()
技术here的原始帖子。
【讨论】:
【参考方案2】:当您首先替换原始字符串中稍后出现的字符串时,您不必担心移动索引。为此,您可以按相反的顺序对替换列表进行排序:
function mreplace(str, repl)
repl.sort(function(a, b)
if (a[0] < b[0]) return 1;
if (a[1] > b[1]) return -1;
return 0;
);
for (var i = 0; i < repl.length; i++)
var begin = repl[i][0];
var end = repl[i][1];
var s = repl[i][2];
str = str.substr(0, begin) + s + str.substr(end);
return str;
var str = mreplace("I want to go to India", [
[2, 6, '<span id="7">want</span>'],
[10, 12, '<span id="49">go</span>'],
[0, 1, '<span id="1003">I</span>']
]);
console.log(str);
// "<span id="1003">I</span> <span id="7">want</span> to <span id="49">go</span> to India"
当两个或多个起始索引相同时,此 sn-p 可能会产生不可预知的结果。因为 Javascript 的排序算法不一定稳定,所以您必须找到其他方法来确保定义的替换顺序。 (您可以通过将原始列表索引推送到每个三元组来使排序稳定,并将其用作辅助排序标准。)
请注意,我在您的示例中更改了开始和结束索引,使它们从零开始,这就是 Javascript 中的索引的工作方式。在我看来,偏离这种索引表示会造成很多混乱。
【讨论】:
以上是关于两个索引之间的多个顺序字符串替换的主要内容,如果未能解决你的问题,请参考以下文章
不止一次用正则表达式替换两个字符串之间的字符串,python