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

JS/React中合并字典数组内同spanid的token_text并保留顺序

合并相同spanid的token_text并保留原数组顺序

需求说明

给定如下字典数组:

const Record = [
  { "tid": 1, "token_text": "Canis", "spanid": 1, "label": "Name" },
  { "tid": 2, "token_text": "Familiaris", "spanid": 1, "label": "Name" },
  { "tid": 3, "token_text": "is" },
  { "tid": 4, "token_text": "the" },
  { "tid": 5, "token_text": "scientific" },
  { "tid": 6, "token_text": "name" },
  { "tid": 7, "token_text": "of" },
  { "tid": 8, "token_text": "dog", "spanid": 2, "label": "species" },
  { "tid": 9, "token_text": "." }
];

需要实现:

  • 相同spanid的元素,将token_text拼接为空格分隔的字符串
  • 保留该spanid首次出现的tid和label
  • 严格保持原数组的元素顺序

最终期望结果:

const mergedRecord = [
  { "tid": 1, "token_text": "Canis Familiaris", "spanid": 1, "label": "Name" },
  { "tid": 3, "token_text": "is" },
  { "tid": 4, "token_text": "the" },
  { "tid": 5, "token_text": "scientific" },
  { "tid": 6, "token_text": "name" },
  { "tid": 7, "token_text": "of" },
  { "tid": 8, "token_text": "dog", "spanid": 2, "label": "species" },
  { "tid": 9, "token_text": "." }
];

现有代码问题分析

你尝试的循环代码仅收集了相同spanid的tid,没有完成token_text拼接、结果对象构建和去重逻辑,所以无法达到需求。


解决方案

方案一:基于你的循环思路改进

通过遍历数组+已处理spanid跟踪,实现合并逻辑:

const mergeRecords = (records) => {
  const processedSpanIds = new Set();
  const result = [];

  for (let i = 0; i < records.length; i++) {
    const current = records[i];

    // 无spanid的元素直接加入结果
    if (!current.spanid) {
      result.push({...current});
      continue;
    }

    // 已处理过的spanid直接跳过
    if (processedSpanIds.has(current.spanid)) {
      continue;
    }

    // 收集所有同spanid的元素
    const sameSpanItems = records.filter(item => item.spanid === current.spanid);
    // 构建合并后的对象
    const mergedItem = {
      tid: sameSpanItems[0].tid,
      token_text: sameSpanItems.map(item => item.token_text).join(' '),
      spanid: current.spanid,
      label: sameSpanItems[0].label
    };

    result.push(mergedItem);
    processedSpanIds.add(current.spanid);
  }

  return result;
};

// 使用示例
const mergedResult = mergeRecords(Record);
console.log(mergedResult);

方案二:用Array.reduce高效实现

一次遍历完成合并,时间复杂度O(n),更适合大数据量场景:

const mergeRecords = (records) => {
  const cache = {}; // 缓存spanid对应的结果项索引
  const result = [];

  records.forEach(item => {
    if (!item.spanid) {
      result.push({...item});
      return;
    }

    if (cache[item.spanid] !== undefined) {
      // 已存在该spanid,追加token_text
      const targetIndex = cache[item.spanid];
      result[targetIndex].token_text += ` ${item.token_text}`;
    } else {
      // 首次遇到该spanid,创建新项并缓存索引
      const newItem = {...item};
      result.push(newItem);
      cache[item.spanid] = result.length - 1;
    }
  });

  return result;
};

// 使用示例
const mergedResult = mergeRecords(Record);
console.log(mergedResult);

关键说明

  • 两种方案均保留原数组顺序,且优先保留同spanid元素首次出现的tid和label
  • 方案二的reduce方式仅遍历一次数组,效率更高;方案一逻辑更直观,适合理解基础循环逻辑
  • 若同spanid元素在原数组中不连续,两种方案均能正确处理

内容的提问来源于stack exchange,提问作者Priyankar Bose

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:17:26