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

如何利用第三方返回的offset值正确用HTML标签包裹标记词?

问题:HTML标签包裹标记词时替换位置错误

场景说明

原始段落文本:

Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense.\nHi, my nme is John, and I am from uas.

第三方返回的标记词数据:

[
  { offset: 7, token: 'nme', type: 'UnknownToken' },
  { offset: 52, token: 'dones', type: 'UnknownToken' },
  { offset: 58, token: 'mke', type: 'UnknownToken' }
]

期望效果:用<span class="underline">包裹每个标记词,例如:

<span class="underline">nme</span>

错误代码及输出

用户的处理逻辑:

function replaceAt(str, index, replacement) {
  return (
    str.substring(0, index) +
    replacement +
    str.substring(index + replacement.length)
  );
}

let input = `Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense\nHi, my nme is John, and I am from uas.`;
const flagTokens = [
  { offset: 7, token: "nme", type: "UnknownToken" },
  { offset: 52, token: "dones", type: "UnknownToken" },
  { offset: 58, token: "mke", type: "UnknownToken" },
];

flagTokens.forEach((item) => {
  input = replaceAt(
    input,
    item.offset,
    `<span class="underline">${item.token}</span>`
  );
});

console.log("Output:", input);

错误输出:

Hi, my <span class="underline">nme</span>his sentce <span <span class="underline">mke</span>

问题原因

  1. 替换顺序错误:按offset从小到大替换时,每次替换会增加字符串长度,导致后续基于原始字符串的offset位置完全偏移。
  2. replaceAt函数逻辑错误:替换时应该切掉原token的长度,而非replacement的长度。原函数中str.substring(index + replacement.length)的写法错误,会保留原token的部分内容,同时截断后续文本。

解决方案

步骤1:修正replaceAt函数

替换时截取原token长度的内容,确保原标记词被完整替换:

function replaceAt(str, index, originalLength, replacement) {
  return str.substring(0, index) + replacement + str.substring(index + originalLength);
}

步骤2:按offset从大到小排序标记数组

先替换位置靠后的标记,避免前面的替换操作改变后续标记的原始offset:

flagTokens.sort((a, b) => b.offset - a.offset);

完整修正代码

function replaceAt(str, index, originalLength, replacement) {
  return str.substring(0, index) + replacement + str.substring(index + originalLength);
}

let input = `Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense\nHi, my nme is John, and I am from uas.`;
const flagTokens = [
  { offset: 7, token: "nme", type: "UnknownToken" },
  { offset: 52, token: "dones", type: "UnknownToken" },
  { offset: 58, token: "mke", type: "UnknownToken" },
];

// 按offset从大到小排序,避免前面的替换影响后面的位置
flagTokens.sort((a, b) => b.offset - a.offset);

flagTokens.forEach((item) => {
  const replacement = `<span class="underline">${item.token}</span>`;
  input = replaceAt(input, item.offset, item.token.length, replacement);
});

console.log("Output:", input);

正确输出

Hi, my <span class="underline">nme</span> is John, and I am from uas.
this sentce <span class="underline">dones</span> <span class="underline">mke</span> sense
Hi, my <span class="underline">nme</span> is John, and I am from uas.

内容的提问来源于stack exchange,提问作者Ven Nilson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:35:21