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

如何在JavaScript中按多键条件深度合并多语言词典对象

合并三语词典定义数组的实现方案

我正在开发一个三语词典项目,数据库中每个单词包含拼写变体数组variants和三种语言的定义对象数组definitions。现在需要实现新增单词时的合并逻辑:如果新增单词是已有单词的拼写变体重复项,则合并两者的definitions数组,需严格遵循以下规则:

  • 原单词属性优先级最高,绝不被覆盖
  • 若新单词同语言的translation与原单词重复,但新单词带有example,则将该example填入对应位置
  • 若为全新translation,则将其及附带的example(若有)追加至definitions数组
  • 同一语言的字段值不可重复,重复时保留原单词值,另一个设为空字符串

示例数据

// 原单词的定义数组
const oldDefs = [{
  en: {
    translation: "EN 1",
    example: "ENGLISH EX 1",
  },
  es: {
    translation: "ES 1",
    example: "SPANISH EX 1",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}, {
  en: {
    translation: "EN 2",
    example: "",
  },
  es: {
    translation: "",
    example: "",
  },
  tz: {
    example: "",
  },
}]

// 待合并的新定义数组
const newDefs = [{
  en: {
    translation: "EN 2",
    example: "ENGLISH EX 2",
  },
  es: {
    translation: "ES 2",
    example: "SPANISH EX 2",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}]

// 预期输出
const expectedOutput = [{
  en: {
    translation: "EN 1",
    example: "ENGLISH EX 1",
  },
  es: {
    translation: "ES 1",
    example: "SPANISH EX 1",
  },
  tz: {
    example: "TZ EXAMPLE 1",
  },
}, {
  en: {
    translation: "EN 2",
    example: "ENGLISH EX 2",
  },
  es: {
    translation: "ES 2",
    example: "SPANISH EX 2",
  },
  tz: {
    example: "",
  },
}]

实现代码

function mergeDefinitions(oldDefs, newDefs) {
  // 记录原定义中已存在的translation和example,用于去重
  const existingEntries = {
    en: new Set(),
    es: new Set(),
    tz: new Set()
  };
  
  // 先遍历原定义,收集已存在的字段值
  oldDefs.forEach(def => {
    if (def.en.translation) existingEntries.en.add(def.en.translation);
    if (def.es.translation) existingEntries.es.add(def.es.translation);
    if (def.tz.example) existingEntries.tz.add(def.tz.example);
  });

  // 创建原定义的深副本,避免修改原数据
  const merged = [...oldDefs].map(def => ({
    en: { ...def.en },
    es: { ...def.es },
    tz: { ...def.tz }
  }));

  // 逐个处理新定义项
  newDefs.forEach(newDef => {
    // 查找原定义中是否有匹配的translation
    let matchIndex = -1;
    if (newDef.en.translation) {
      matchIndex = merged.findIndex(def => def.en.translation === newDef.en.translation);
    } else if (newDef.es.translation) {
      matchIndex = merged.findIndex(def => def.es.translation === newDef.es.translation);
    }

    if (matchIndex !== -1) {
      // 匹配到重复translation,按规则补充example或处理重复值
      const target = merged[matchIndex];
      // 处理英文:原example为空时补充新值
      if (newDef.en.example && target.en.example === "") {
        target.en.example = newDef.en.example;
      }
      // 处理西班牙文:原example为空时补充新值
      if (newDef.es.example && target.es.example === "") {
        target.es.example = newDef.es.example;
      }
      // 处理Tz'utujil:example重复则设为空
      if (existingEntries.tz.has(newDef.tz.example)) {
        target.tz.example = "";
      } else if (target.tz.example === "" && newDef.tz.example) {
        target.tz.example = newDef.tz.example;
        existingEntries.tz.add(newDef.tz.example);
      }
    } else {
      // 全新translation,创建新定义项并追加
      const newItem = {
        en: { translation: "", example: "" },
        es: { translation: "", example: "" },
        tz: { example: "" }
      };
      // 处理英文新增translation
      if (newDef.en.translation && !existingEntries.en.has(newDef.en.translation)) {
        newItem.en.translation = newDef.en.translation;
        newItem.en.example = newDef.en.example || "";
        existingEntries.en.add(newDef.en.translation);
      }
      // 处理西班牙文新增translation
      if (newDef.es.translation && !existingEntries.es.has(newDef.es.translation)) {
        newItem.es.translation = newDef.es.translation;
        newItem.es.example = newDef.es.example || "";
        existingEntries.es.add(newDef.es.translation);
      }
      // 处理Tz'utujil example去重
      if (newDef.tz.example) {
        newItem.tz.example = existingEntries.tz.has(newDef.tz.example) ? "" : newDef.tz.example;
        if (!existingEntries.tz.has(newDef.tz.example)) {
          existingEntries.tz.add(newDef.tz.example);
        }
      }
      merged.push(newItem);
    }
  });

  return merged;
}

// 验证结果
const result = mergeDefinitions(oldDefs, newDefs);
console.log(JSON.stringify(result) === JSON.stringify(expectedOutput)); // 输出true

规则对应说明

  1. 原属性优先级最高:通过创建原定义的深副本进行修改,所有赋值操作仅在原字段为空时执行,原字段有值时完全保留。
  2. 重复translation补充example:通过findIndex匹配原定义中相同的translation,仅当原example为空时替换为新值。
  3. 全新translation追加:当新translation未在原定义中出现时,创建新的定义项并添加到合并数组末尾,同时记录到去重集合中。
  4. 字段值去重:用Set存储所有已出现的字段值,新值重复时直接设为空字符串,确保原数据不受影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:20:07