【问题标题】: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://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.'

【问题讨论】:

  • 我认为这是试图解决另一个问题的问题 - 也称为“XY problem”。您能否告诉我们,或向我们展示最初的问题是什么,因为这个解决方案感觉过于复杂。
  • 我已经在编辑中提供了上述实际问题的描述。
  • 查看(可能是简化的)输入/输出,这似乎是一个关于如何用特定id 的元素包装某些单词的问题?如果提供的词('want''go''I')的所有实例出现不止一次,是否应该替换,或者只替换特定(初始)索引处的实例?
  • 是的。问题是用特定的 id 包装 str 的某些子字符串。它只需要针对指定的索引发生一次。
  • 继续@DavidThomas 的问题:您需要在什么背景下解决这个问题?不同的跨度ids 代表什么?每个包含“我”的句子都会用&lt;span id="1003"&gt; 包裹这个词吗?所有代词都会被包裹在&lt;span id="1003"&gt; 中吗?还是只有一个字母的所有单词?你是只给了一个“长字符串'str'”来处理,还是你有很多类似的字符串?你能举个例子吗?您对每个字符串中的相同单词使用的ids 是否相同?也许有一个更通用的解决方案可以有效地解决这个问题。

标签: javascript string algorithm replace


【解决方案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 中的索引的工作方式。在我看来,偏离这种索引表示会造成很多混乱。

    【讨论】:

      猜你喜欢
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多