两个索引之间的多个顺序字符串替换

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 = 11end = 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 替换 startend 之间 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 的问题:您需要在什么背景下解决这个问题?不同的跨度ids 代表什么?每个包含“我”的句子都会用&lt;span id="1003"&gt; 包裹这个词吗?所有代词都会被包裹在&lt;span id="1003"&gt; 中吗?还是只有一个字母的所有单词?你是只给了一个“长字符串'str'”来处理,还是你有很多类似的字符串?你能举个例子吗?您对每个字符串中的相同单词使用的ids 是否相同?也许有一个更通用的解决方案可以有效地解决这个问题。 【参考方案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 中的索引的工作方式。在我看来,偏离这种索引表示会造成很多混乱。

【讨论】:

以上是关于两个索引之间的多个顺序字符串替换的主要内容,如果未能解决你的问题,请参考以下文章

notepad++如何替换两个字符之间的内容?内容跨行

正则匹配指定字符之间的内容,并替换(多个匹配替换)

不止一次用正则表达式替换两个字符串之间的字符串,python

Netezza SQL - 如何用条件替换两个逗号之间的字符串

如何多次替换两个分隔符/字符串之间的唯一字符串

如何仅替换不在 c# 中的两个引号之间的字符串