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

高效生成分类JSON数组:三种实现方案的效率对比问询

哪种方法生成目标JSON的效率最高?

针对你描述的场景(用户选择项数量在1-100之间),方法C的效率是最高的——它通过增量更新维护JSON结构,避免了每次操作都全量遍历DOM或重建整个数据结构的冗余开销。下面我来逐个分析三种方法的优劣,再给出方法C的具体实现思路:


方法A:点击按钮时批量处理

这种方法的核心是只在用户点击exec按钮时才开始处理数据:先把DOM中的选择项转成扁平的临时数组,再按类别分组。

缺点:

  • 冗余操作:每次点击按钮都要遍历全部选择项(最多100次),先转临时数组再分组,相当于两次全量遍历;
  • 临时数组额外占用内存,虽然100项的内存可以忽略,但属于没必要的开销;
  • 如果用户频繁点击按钮,重复处理的成本会累积。

方法B:每次选择后全量重建JSON

这种方法每次用户选择/取消选择项时,都重新遍历整个user_selection_list来构建data_json。

缺点:

  • 重复劳动:比如用户选了100次,每次都要遍历最多100个DOM元素,总遍历次数是100*100=10000次——虽然100项的量级下不会卡顿,但完全是没必要的重复工作;
  • DOM遍历本身比内存中操作数据要慢,每次全量遍历DOM都会带来额外的性能开销。

方法C:增量更新JSON结构(最优解)

这种方法的核心是只针对当前操作的项来更新data_json,而不是每次都全量重建:

  1. 当用户添加项时:检查data_json中是否存在对应类别,不存在则新建类别并添加item;存在则直接把item加入对应类别的列表;
  2. 当用户移除项时:找到对应类别,删除item;如果类别下没有item了,就删掉整个类别对象。

为什么高效?

  • 每次操作只需要处理当前项,最多遍历一次data_json的类别数组(类别数量远小于100,比如示例里只有A/B/C三个),时间复杂度极低;
  • 点击exec按钮时直接用已经维护好的data_json,不需要任何额外处理;
  • 避免了重复遍历DOM或全量重建数据结构的冗余开销。

具体实现示例(原生JS)

// 初始化目标JSON数组
let data_json = [];

// 先同步初始的user_selection_list到data_json
document.querySelectorAll('.user_selection_list li').forEach(li => {
  const category = li.dataset.category;
  const item = li.dataset.item;
  updateDataJson(category, item, true);
});

// 处理full_list中项的点击事件(添加/移除到选择列表)
function handleItemClick(e) {
  const targetLi = e.target.closest('li');
  if (!targetLi) return;

  const category = targetLi.dataset.category;
  const item = targetLi.dataset.item;
  const selectionList = document.querySelector('.user_selection_list');
  const existingLi = selectionList.querySelector(`li[data-category="${category}"][data-item="${item}"]`);

  if (existingLi) {
    // 移除已选项
    selectionList.removeChild(existingLi);
    updateDataJson(category, item, false);
  } else {
    // 添加新选项
    const newLi = targetLi.cloneNode(true);
    selectionList.appendChild(newLi);
    updateDataJson(category, item, true);
  }
}

// 核心:增量更新data_json的函数
function updateDataJson(category, item, isAdd) {
  const categoryObj = data_json.find(obj => obj.category === category);

  if (isAdd) {
    if (!categoryObj) {
      // 类别不存在,新建类别对象
      data_json.push({ category, items: [item] });
    } else if (!categoryObj.items.includes(item)) {
      // 类别存在,item未添加,加入列表
      categoryObj.items.push(item);
    }
  } else {
    if (categoryObj) {
      // 移除item
      categoryObj.items = categoryObj.items.filter(i => i !== item);
      // 如果类别下已无item,删除该类别
      if (categoryObj.items.length === 0) {
        data_json = data_json.filter(obj => obj.category !== category);
      }
    }
  }
}

// exec按钮点击事件:直接使用已维护好的data_json
function execute() {
  console.log('最终JSON:', data_json);
  // 这里可以把data_json用于后续逻辑,比如提交接口等
}

// 绑定full_list的点击事件
document.querySelector('.full_list').addEventListener('click', handleItemClick);

优化版本(用对象存储类别,查找更快)

如果你的类别数量较多(比如超过10个),可以把data_json改成以类别为key的对象,这样查找类别的时间复杂度是O(1),效率更高:

// 改用对象存储,类别查找更快
let data_map = {};

function updateDataMap(category, item, isAdd) {
  if (isAdd) {
    if (!data_map[category]) data_map[category] = [];
    if (!data_map[category].includes(item)) data_map[category].push(item);
  } else {
    if (data_map[category]) {
      data_map[category] = data_map[category].filter(i => i !== item);
      if (data_map[category].length === 0) delete data_map[category];
    }
  }
}

// exec按钮点击时转成需要的数组格式
function execute() {
  const data_json = Object.entries(data_map).map(([category, items]) => ({ category, items }));
  console.log('最终JSON:', data_json);
}

总结:在1-100项的选择场景下,方法C的增量更新方式不仅效率最高,而且代码逻辑更清晰,避免了不必要的重复操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:17:50