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

React Reducer中基于x、y键实现对象数组去重的最优方案

最优实现:React Reducer中基于x/y值的数组去重(适配Socket实时更新)

针对你在React reducer里处理Socket实时推送数据、需要按x和y值去重的需求,这里有几个高效的实现方案,按性能和易用性排序推荐:

方案1:使用Map构建唯一键值对(最优推荐)

这个方案的时间复杂度是O(n),键查找和插入都是常数时间,非常适合频繁更新的Socket场景,代码简洁且符合Redux纯函数要求。

核心思路是用x-y的字符串组合作为唯一键,利用Map会自动覆盖重复键的特性,保留最后出现的(也就是最新的)对象:

// 在你的Reducer处理Socket更新的case中
case 'SOCKET_UPDATE_DATA': {
  // 场景1:如果Socket返回的是增量数据,需要和现有state合并
  const combinedData = [...state, ...action.payload];
  
  // 用x+y的组合作为唯一键,Map会自动覆盖重复键的旧值
  const uniqueDataMap = new Map(combinedData.map(item => [`${item.x}-${item.y}`, item]));
  
  // 转换回数组作为新state
  return Array.from(uniqueDataMap.values());

  // ------------------------------
  // 场景2:如果Socket返回的是完整的全量数据,直接处理新数据即可
  // const uniqueDataMap = new Map(action.payload.map(item => [`${item.x}-${item.y}`, item]));
  // return Array.from(uniqueDataMap.values());
}

优势

  • 性能拉满:不管数组多大,处理速度线性增长,适配高频Socket更新
  • 逻辑清晰:一行代码完成去重映射,可读性强
  • 纯函数操作:完全符合Redux reducer的无副作用要求

方案2:使用Set配合filter(小数据量可选)

如果你的数据量很小,也可以用Set记录已出现的键,配合filter去重。但要注意:默认filter会保留第一个出现的对象,如果要保留最新的,需要先反转数组再处理:

case 'SOCKET_UPDATE_DATA': {
  const combinedData = [...state, ...action.payload];
  const seenKeys = new Set();

  // 保留最新的对象(后出现的)
  return combinedData
    .reverse()
    .filter(item => {
      const key = `${item.x}-${item.y}`;
      if (seenKeys.has(key)) return false;
      seenKeys.add(key);
      return true;
    })
    .reverse();
}

这个方案同样是O(n)时间复杂度,但多了两次数组反转操作,性能略逊于Map方案,适合数据量不大的场景。


自定义去重规则(可选)

如果不是简单保留最新对象,而是需要按其他规则选择保留的对象(比如test值最大的),可以在遍历的时候做判断:

case 'SOCKET_UPDATE_DATA': {
  const combinedData = [...state, ...action.payload];
  const uniqueDataMap = new Map();

  combinedData.forEach(item => {
    const key = `${item.x}-${item.y}`;
    const existingItem = uniqueDataMap.get(key);
    
    // 示例:保留test数值更大的对象
    if (!existingItem || parseFloat(item.test) > parseFloat(existingItem.test)) {
      uniqueDataMap.set(key, item);
    }
  });

  return Array.from(uniqueDataMap.values());
}

注意事项

  • 确保x和y的类型一致:如果你的数据中x/y可能混合字符串和数字,记得统一转成字符串(比如String(item.x)-String(item.y)),避免出现"1"-"2"和1-2被当成不同键的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:19:23