You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JS中合并同一初始字符串的多版本修改结果?

如何合并基于同一初始文本的两个修改版本?

已知三个字符串:

  • str0:初始文本
  • str1:初始文本的一个修改版本
  • str2:初始文本的另一个修改版本

需要生成融合两个版本所有修改的最终字符串,举个例子:

str0 = "This is quite a short text";
str1 = "This is quite a text";
str2 = "This is QUITE a short text";
merge(str0, [str1, str2])

// 应返回 "This is QUITE a text"

目前可以用jsdiff库的Diff.diffWords函数,对比str0与str1、str2,得到将初始文本转换为对应修改版本的变更列表:
比如Diff.diffWords(str0, str1)返回:

[
   { value: "This is quite a " },
   { removed: true, value: "short" },
   { value: "text" }
]

Diff.diffWords(str0, str2)返回:

[
   { value: "This is " },
   { removed: true, value: "quite" },
   { added: true, value: "QUITE" },
   { value: " a short text" }
]

下面是可行的合并思路与算法步骤:

核心合并逻辑(参考三方合并思想)

本质上这是基于共同祖先(str0)的三方合并,和Git等版本控制系统的文本合并逻辑一致,步骤如下:

1. 标记化初始文本

按照diffWords的拆分规则,把str0拆分成单词、空白符组成的标记序列,给每个标记分配唯一索引。比如示例中str0的标记序列为:
["This", " ", "is", " ", "quite", " ", "a", " ", "short", " ", "text"],对应索引0到10。

2. 解析变更列表为操作集

把两个diff结果转换成针对标记索引的明确操作:

  • 对于str0→str1的diff:识别出删除操作——移除索引8的标记("short")
  • 对于str0→str2的diff:识别出修改操作——将索引4的标记("quite")替换为"QUITE"

3. 冲突检测与处理

如果两个修改操作针对同一标记/位置(比如一个修改、一个删除,或者两个不同的修改内容),需要提前定义冲突处理规则:

  • 优先保留某一个版本的修改
  • 标记冲突区域,提示用户手动处理
  • 特殊场景下合并修改(比如文本拼接,这类情况较少见)

你的示例中两个操作的位置不重叠,无冲突,可以直接合并。

4. 构建最终文本

基于初始标记序列,依次应用所有非冲突操作:

  1. 先执行修改操作:把索引4的"quite"替换为"QUITE"
  2. 再执行删除操作:移除索引8的"short"
  3. 将剩余标记按顺序拼接,得到最终结果:"This is QUITE a text"

基于jsdiff结果的简化实现思路

不需要手动拆分初始文本的标记,可以通过遍历两个diff变更块,对齐它们在初始文本中的位置:

  • 维护一个指向str0当前位置的指针,同步遍历两个diff列表
  • 对每个变更块,判断它在str0中的覆盖范围,记录对应的删除/修改操作
  • 合并操作集时,跳过重复操作,处理冲突后按顺序应用到初始文本上

内容的提问来源于stack exchange,提问作者Robin LP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:32:49