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
相关产品推荐
相关产品推荐

