在两个索引之间进行多次顺序字符串替换

3
我是一名有用的助手,可以为您翻译文本。下面是需要翻译的内容:

我有一个长字符串'str'和一个三元组列表,形式为[start,end,replace_str]。 我需要遍历三元组列表,并将在起始索引和结束索引之间的'str'内容替换为replace_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'.

现在进行第二次三元组替换,起始位置为11结束位置为13,字符串将会变成:

'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://stackoverflow.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.'

1
我认为这是另一个问题的尝试解决方案的问题 - 也就是所谓的"XY问题"。你能告诉我们原来的问题是什么,或者展示一下吗?因为这个解决方案感觉过于复杂了。 - David Thomas
我已经在编辑中提供了实际问题的描述。 - swap310
从(可能是简化的)输入/输出来看,这似乎是一个关于如何用特定id的元素包装某些单词的问题?如果提供的单词('want'、'go'和'I')的所有实例(如果它们出现了多次)都应该被替换,还是只有在特定(初始)索引处的那些实例? - David Thomas
是的。问题是使用特定的ID包装str的某些子字符串。并且它只需要针对指定的索引发生一次。 - swap310
继@DavidThomas的问题之后:您需要解决这个问题的情境是什么?不同的span id代表什么?每个包含"I"的句子都会用<span id="1003">括起来吗?所有代词都会用<span id="1003">括起来吗?还是只有一个字母的所有单词都会被括起来?你只有一个“长字符串'str'”来处理,还是你有许多相似的字符串?能给出例子吗?您在每个字符串中使用的id是否相同?也许有一种更通用的解决方案可以有效地处理这个问题。 - James Newton
2个回答

3

当您首先替换原始字符串中后出现的字符串时,无需担心移动索引。为此,您可以按其起始索引的相反顺序对替换列表进行排序:

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"

当两个或更多起始索引相同时,此代码段可能会产生不可预测的结果。由于Javascript的排序算法不一定是稳定的,你必须找到其他方式来确保定义的替换顺序。(你可以通过将原始列表索引推送到每个三元组中并将其用作次要排序准则来使排序稳定。)

请注意,我已更改了你示例中的起始和结束索引,以使它们基于零,这是Javascript中索引的工作方式。在我看来,偏离这种索引表示会造成很多混淆。


3
假设替换的三元组从未重叠,那么您可以从末尾开始向前工作:
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()技术的原始帖子:这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接