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

如何通过对比新旧数组识别拖拽后位置变动的元素

如何通过对比新旧数组确定被拖拽的元素

场景说明

我们有一个代表可拖拽HTML元素的数组,元素顺序可通过拖拽改变。示例如下:

拖拽前的旧数组:

let oldArr = 
  [{id: 'id1'}, {id: 'id2'}, {id: 'id3'}, {id: 'id4'}, {id: 'id5'}, {id: 'id6'}]

将元素id5拖拽至索引2的位置后,得到新数组:

let newArr = 
  [{id: 'id1'}, {id: 'id2'}, {id: 'id5'}, {id: 'id3'}, {id: 'id4'}, {id: 'id6'}]

需求是通过对比新旧数组,确定哪个元素被拖拽到了新位置;若仅两个相邻元素交换顺序,无法判定时返回任意一个即可。

解决方案

核心思路

通过提取元素的唯一标识(这里是id)对比位置变化,找到发生跳跃性移动的元素:

  1. 先将两个数组转换为仅包含id的序列,简化对比逻辑
  2. 遍历序列,找到第一个元素不匹配的索引位置
  3. 追踪该位置元素在另一个数组中的原始位置,判断是否为被拖拽的目标元素
  4. 相邻交换场景下,两个元素位置均变化,返回任意一个即可

代码实现

function findDraggedElement(oldArr, newArr) {
  const oldIds = oldArr.map(item => item.id);
  const newIds = newArr.map(item => item.id);
  
  for (let i = 0; i < oldIds.length; i++) {
    if (oldIds[i] !== newIds[i]) {
      // 查找新数组当前元素在旧数组中的位置
      const oldPos = oldIds.indexOf(newIds[i]);
      if (oldPos !== -1 && oldPos !== i) {
        return newArr[i];
      }
      // 查找旧数组当前元素在新数组中的位置
      const newPos = newIds.indexOf(oldIds[i]);
      if (newPos !== -1 && newPos !== i) {
        return oldArr[i];
      }
      // 相邻交换场景,返回任意一个元素
      return newArr[i];
    }
  }
  // 数组无变化时返回null
  return null;
}

// 测试示例
const oldArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id3'}, {id: 'id4'}, {id: 'id5'}, {id: 'id6'}];
const newArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id5'}, {id: 'id3'}, {id: 'id4'}, {id: 'id6'}];
console.log(findDraggedElement(oldArr, newArr)); // 输出:{id: 'id5'}

// 测试相邻交换场景
const oldArr2 = [{id: 'a'}, {id: 'b'}];
const newArr2 = [{id: 'b'}, {id: 'a'}];
console.log(findDraggedElement(oldArr2, newArr2)); // 输出:{id: 'b'}(或{id: 'a'},取决于逻辑顺序)

逻辑说明

  • 该方法针对单元素拖拽的常见场景设计,能快速定位被移动的元素
  • 若数组完全未发生变化,返回null
  • 相邻元素交换时,因无法判定哪个是主动拖拽的元素,代码会优先返回新数组第一个差异位置的元素,符合题目要求

内容的提问来源于stack exchange,提问作者Axel Productions 86

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:52:27