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

JavaScript检测嵌套对象子属性重复项并标记error的实现方法

姓名重复校验实现方案

你原有代码存在几个可优化点和问题:

  • 字段笔误:遍历儿童列表时写的是room.childs,实际数据结构中对应字段为children,会导致遍历不到儿童数据
  • 性能问题:每次判断重复都全量遍历已存姓名数组,时间复杂度为O(n²),数据量大时运行效率低
  • 逻辑偏差:原有逻辑仅标记第一个出现姓名之后的重复项,和你给出的期望输出(所有同名重复项均标记)不匹配
  • 冗余字段:无错误的人员会被赋值为空字符串的error属性,和期望输出结构(无错人员无error字段)不符
  • 残留问题:用户修改姓名后重新校验时,旧的错误标记不会被清除,容易出现误判

优化后实现代码

核心思路是分两次遍历:第一次统计所有姓名组合的出现频次,第二次根据频次给对应人员加/删错误标记,整体时间复杂度O(n),性能更好,逻辑更清晰:

const validateNames = (rooms) => {
  const nameCountMap = new Map();
  // 第一次遍历:统计每个 名+姓 组合的出现次数
  rooms.forEach(room => {
    // 合并成人、儿童数组统一处理,减少重复代码
    [...room.adults, ...room.children].forEach(person => {
      // 用特殊分隔符拼接名和姓作为key,避免名/姓本身的字符导致key冲突,加trim处理首尾空格
      const nameKey = `${person.first.trim()}|${person.last.trim()}`;
      nameCountMap.set(nameKey, (nameCountMap.get(nameKey) || 0) + 1);
    });
  });

  // 第二次遍历:标记重复项,清除非重复项的旧错误标记
  rooms.forEach(room => {
    [...room.adults, ...room.children].forEach(person => {
      const nameKey = `${person.first.trim()}|${person.last.trim()}`;
      if (nameCountMap.get(nameKey) > 1) {
        person.error = "Duplicate name, please update.";
      } else {
        delete person.error;
      }
    });
  });
};

Vue3 中使用方式

因为你是接收的prop数据,只修改人员对象的内部属性不会违反Vue单向数据流规则,响应式可以正常追踪,配合watch可以实现数据变化自动校验:

import { watch, defineProps } from 'vue';

const props = defineProps({
  rooms: {
    type: Array,
    required: true
  }
});

// 深度监听rooms数据,初始化和数据变化时自动执行校验
watch(
  () => props.rooms,
  () => validateNames(props.rooms),
  { deep: true, immediate: true }
);

补充说明

  • 代码中加了trim()处理首尾空格,可以避免用户输入时不小心打了多余空格,导致内容相同的姓名被判定为不重复的问题
  • 如果你实际需求是「仅标记第一个出现姓名之后的重复项,第一个出现的不标记」,只需要把第一次遍历的逻辑改成记录已出现的key,第二次遍历时遇到已存在的key就标记,未存在的就存入key即可
  • 不要直接替换整个rooms数组或者room对象,仅修改内部person的属性,不会触发Vue的prop修改警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:36:20