当前位置: 首页 > 知识库问答 >
问题:

javascript - js请教:如何比较两个数组的数据变动情况?

宗政子琪
2023-07-14

第一个数组对象,有些没记录电话

const oldList = [  { department: '部门1', name: '姓名1', phone: '11111'},  { department: '部门2', name: '姓名2', phone: '22222' },  { department: '部门3', name: '姓名3' }];

第二个数组对象,有一些改动

const newList = [  { department: '部门2', name: '姓名2', phone: '77777' },  { department: '部门3', name: '姓名3', phone: '88888' },  { department: '部门4', name: '姓名4', phone: '99999' }];

想要得到一个电话变动情况表:

const changeList = [  { department: '部门1', name: '姓名1', change:'旧号码11111新号码(空)' },  { department: '部门2', name: '姓名2', change:'旧号码22222新号码77777' },  { department: '部门3', name: '姓名3', change:'旧号码(空)新号码88888' },  { department: '部门4', name: '姓名4', change:'旧号码(空)新号码99999' }]

共有4个答案

敖硕
2023-07-14
Object.values([old, new_].reduce((obj, arr, idx) =>     arr.reduce((obj, {phone, ...rest}) => {        ((obj[rest.name] ??= rest).phone ??= [])[idx] = phone;        return obj;    }, obj), {})).map(({phone: [old, new_], ...rest}) => ({    ...rest,    change: `旧号码${old ?? '(空)'}新号码${new_ ?? '(空)'}`}))
戴嘉珍
2023-07-14

Edit

啊,读题错误……正确的是借助 Array.reduce() 即可,因为你需要的是一个展示变更操作的结果。

const oldList = [  { department: '部门1', name: '姓名1', phone: '11111'},  { department: '部门2', name: '姓名2', phone: '22222' },  { department: '部门3', name: '姓名3' }];const newList = [  { department: '部门2', name: '姓名2', phone: '77777' },  { department: '部门3', name: '姓名3', phone: '88888' },  { department: '部门4', name: '姓名4', phone: '99999' }];// 修改记录列表, 因为可能修改时会删除一些记录,所以展开了新旧数据一起循环。// 因为需要先填入旧数据,所以先展开 oldList,然后展开 newList。const changeList = [...oldList, ...newList].reduce((changeList, currentData) => {  // 是否已经添加到修改记录列表中,如果已经添加则返回添加了的记录。  const added = changeList.find(data => data.name === currentData.name)  // 如果已经添加过了,则开始设置 newPhone 属性  if(added) {     added.newPhone = currentData.phone  } else {    // 如果没有修改则添加到修改列表中    // 因为担心修改源数据会造成一些其它的业务问题,所以这边添加时做了浅拷贝。    changeList.push({ ...currentData, newPhone: '' })  }  return changeList}, [])// 获得的变更记录// (4) [{…}, {…}, {…}, {…}]//   0: {department: '部门1', name: '姓名1', phone: '11111', newPhone: ''}//   1: {department: '部门2', name: '姓名2', phone: '22222', newPhone: '77777'}//   2: {department: '部门3', name: '姓名3', newPhone: '88888'}//   3: {department: '部门4', name: '姓名4', phone: '99999', newPhone: ''}//   length: 4

这个时候修改记录列表中已经有了所有的人员记录,以及他们各自的新旧电话号码,因为你最终要还需要有一个 change 属性来记录变更内容,所以再借助 Array.map() 来处理组装即可:

const changeResultList = changeList.map(data => {  return {     ...data,     change: `旧号码:${data.phone || '(空)'},新号码:${data.newPhone || '(空)'}`  }})// 获得的变更结果记录// (4) [{…}, {…}, {…}, {…}]//   0: {department: '部门1', name: '姓名1', phone: '11111', newPhone: '', change: '旧号码:11111,新号码:(空)'}//   1: {department: '部门2', name: '姓名2', phone: '22222', newPhone: '77777', change: '旧号码:22222,新号码:77777'}//   2: {department: '部门3', name: '姓名3', newPhone: '88888', change: '旧号码:(空),新号码:88888'}//   3: {department: '部门4', name: '姓名4', phone: '99999', newPhone: '', change: '旧号码:99999,新号码:(空)'}//   length: 4

其实也可以在 reduce 循环的时候一起处理掉,但是我怕OP你不好理解,所以拆分成两步,最后又 map 循环拼接了一次数据。

如果不想多一次 map 操作,可以像下面这样修改 reduce 的代码,就可以一次性全部处理好了。

const changeList = [...oldList, ...newList].reduce((changeList, currentData) => {  const added = changeList.find(data => data.name === currentData.name)  if(added) {     added.newPhone = currentData.phone     added.chanmge = `旧号码:${currentData.phone || '(空)'},新号码:${currentData.newPhone || '(空)'}`  } else {    changeList.push({ ...currentData, newPhone: '', change: `旧号码:${currentData.phone || '(空)'},新号码:(空)}` })  }  return changeList}, [])

以下是旧的错误回答

一般会借助现有的轮子,比如说 lodash。里面就有提供各种 diff 的工具函数。
你当前的需求就是 _.differenceBy 这个函数,所以直接用就行了。

const oldList = [  { department: '部门1', name: '姓名1', phone: '11111'},  { department: '部门2', name: '姓名2', phone: '22222' },  { department: '部门3', name: '姓名3' }];const newList = [  { department: '部门2', name: '姓名2', phone: '77777' },  { department: '部门3', name: '姓名3', phone: '88888' },  { department: '部门4', name: '姓名4', phone: '99999' }];_.differenceBy(oldList, newList, 'phone');// (3) [{…}, {…}, {…}]//  0: {department: '部门1', name: '姓名1', phone: '11111'}//  1: {department: '部门2', name: '姓名2', phone: '22222'}//  2: {department: '部门3', name: '姓名3'}//  length: 3
宫瀚
2023-07-14
function diffData(a, b) {  const phoneMap = a.reduce((res,v) => (res[v.department+v.name]=v, res),{});  return b.map(({name: n, department: d, phone: p}) => {    const res = {      name: n,      department: d,      change: `旧号码${phoneMap[d+n]?.phone || '(空)'}新号码${p}`     };    delete phoneMap[d+n];    return res;  }).concat(        Object.values(phoneMap).map(({name, department, phone}) => ({name, department, change: `旧号码${phone}新号码(空)`}))    )}
竺焕
2023-07-14

试试chatgpt给的答案是否是你想要的

const oldData = [  { department: '部门1', name: '姓名1', phone: '11111' },  { department: '部门2', name: '姓名2', phone: '22222' },  { department: '部门3', name: '姓名3' }];const newData = [  { department: '部门2', name: '姓名2', phone: '77777' },  { department: '部门3', name: '姓名3', phone: '88888' },  { department: '部门4', name: '姓名4', phone: '99999' }];const changeData = [];// 遍历旧数据for (let i = 0; i < oldData.length; i++) {  const oldItem = oldData[i];  let found = false;  // 在新数据中查找匹配项  for (let j = 0; j < newData.length; j++) {    const newItem = newData[j];    // 判断是否匹配(根据部门和姓名)    if (oldItem.department === newItem.department && oldItem.name === newItem.name) {      found = true;      // 比较电话号码是否发生变化      if (oldItem.phone !== newItem.phone) {        changeData.push({          department: oldItem.department,          name: oldItem.name,          change: `旧号码${oldItem.phone}新号码${newItem.phone}`        });      }      // 退出内层循环      break;    }  }  // 如果在新数据中未找到匹配项,则说明该记录已被删除  if (!found) {    changeData.push({      department: oldItem.department,      name: oldItem.name,      change: `旧号码${oldItem.phone}新号码(空)`    });  }}// 处理新数据中新增的记录for (let i = 0; i < newData.length; i++) {  const newItem = newData[i];  let found = false;  // 在旧数据中查找匹配项  for (let j = 0; j < oldData.length; j++) {    const oldItem = oldData[j];    // 判断是否匹配(根据部门和姓名)    if (newItem.department === oldItem.department && newItem.name === oldItem.name) {      found = true;      break;    }  }  // 如果在旧数据中未找到匹配项,则说明该记录是新增的  if (!found) {    changeData.push({      department: newItem.department,      name: newItem.name,      change: `旧号码(空)新号码${newItem.phone}`    });  }}console.log(changeData);
 类似资料:
  • 我有一个简单的javascript问题,我真的需要一些帮助!我正在尝试弄清楚如何在数组之间比较元素,以及在下一个循环中再次比较较大的元素。假设我们有数组A和数组B。 我的问题是,在比较索引处的元素之后,我希望在下一个循环周期中比较较大的元素。 如果A=[5,7,4],B=[2,8,5] 在第一个循环中,5与2进行比较,2较小,因此会发生一些事情。在下一个循环周期中,我希望5与8进行比较,而对于现在

  • let arr1 = [333,555,222] let arr2 = [100,200,300] arr1 和 arr2 中的每项是对应关系, 请问如何比较 arr1中 最大值的那项,必须对应arr2中的最小值 意思就是说,按正常情况,arr1和arr2的对应关系应为: let arr1 = [333,555,222] let arr2 = [200,100,300] 请问如何去写判断?实际场景

  • js 比较两个数组,并进行替换掉? 需要根据arr2对象里面的val数组里面的值[200, 300, 500]去匹配arr1数组下sk数组里面的Value的值,如果arr1数组下sk数组里面的Value的值和arr2对象里面的val数组里面的值相等就替换Name,把arr2 对象的name 赋值到sk数组里面的Name 期望得到 这样写了调试了还没效果。麻烦大佬们帮我看看

  • 问题内容: 我有这个间隔,当前每5秒执行一次ajax请求。我对声明有疑问。我的代码总是输入它,并且两个json值完全相同,为什么它认为它们不同? 编辑 这是控制台输出(虚线是分隔请求,它不在实际输出中) 问题答案: 不能保证以相同的方式序列化JSON对象,也不能保证属性以相同的顺序进行序列化,使用并不是测试对象相等性的好方法。 一个更好的例子是这样的函数(前一段时间在互联网上找到,希望我能感谢原始

  • 问题内容: 我必须比较两个对象(不是)。比较它们的规范方法是什么? 我可以想到: 该运营商只比较基准,因此这将仅适用于较低的整数值的工作。但是也许自动装箱开始了…? 这看起来像一个昂贵的操作。是否以此方式计算出哈希码? 有点冗长… 编辑: 谢谢您的答复。尽管我现在知道该怎么办,但事实已分布在所有现有答案(甚至是已删除的答案)上,我也不知道该接受哪个答案。因此,我将接受最佳答案,即所有三种比较可能性

  • 本文向大家介绍JavaScript 数组比较,包括了JavaScript 数组比较的使用技巧和注意事项,需要的朋友参考一下 示例 为了进行简单的数组比较,您可以使用JSON stringify并比较输出字符串: 注意:这仅在两个对象都可以JSON序列化并且不包含循环引用的情况下起作用。可能会抛出TypeError: Converting circular structure to JSON 您可以