javascript - 比较两个嵌套数组和对象以查找差异

标签 javascript arrays algorithm compare

我有两个具有多级嵌套的 JSON 数据。我想通过以下条件进行比较: 1) 如果第一个对象中的名称等于第二个对象中的名称,则比较它们的 prop 数组,否则如果两个对象中没有相同的名称,则返回空数组; 2)比较两个prop数组中的对象并找出差异; 3)返回与第一个和第二个数组不同的新对象。

const p1 = [{
  name: 'B [1]', // name equals and prop differnce, then comparing it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    C: { C: 78, D: 4, T: 7, } }],
  }, {
  name: 'B [2]', // name equals, then skiping it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, Y: 13 } }],
  }, {
  name: 'B [3]', // name equals and prop differnce, then comparing it
  prop: [{ 
    E: { A: 1, B: 2 }, 
    R: { A: 1, B: 2 }, 
    T: { C: 3,  D: 4, } }],
  }, {
  name: 'B [4]', // name and prop equals, then skiping it 
  prop: [{ 
    A: { A: 1, B: 2 }, 
    S: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, } }],
}]

const p2 = [{
  name: 'B [1]', // name equals and prop differnce, then comparing it 
  prop: [{ 
    A: { A: 1, B: 8 }, 
    B: { A: 1, B: 2 }, 
    C: { C: 3, T: 7, O: 9 } }],
  }, {
  name: 'B [6]', // name not equals, then skiping it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4 } }],
  }, {
  name: 'B [3]', // name equals and prop differnce, then comparing it
  prop: [{ 
    E: { A: 1, B: 2 }, 
    R: { A: 1, B: 2, U: 150 }, 
    T: { C: 3,  D: 4, } }],
  }, {
  name: 'B [4]', // name and prop equals, then skiping it 
  prop: [{ 
    A: { A: 1, B: 2 }, 
    S: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, } }],
}]

结果应如下所示:

const result = [{
  name: 'B [1]',
  propOne: [{
    A: { B: 2 },
    C: { C: 78, D: 4, O: 'Missing' }
  }],
  propTwo: [{
    A: { B: 8 },
    C: { C: 3, D: 'Missing', O: 9 }
  }],
  },{
  name: 'B [3]',
  propOne: [{
    R: { U: 'Missing' }
    }],
  propTwo: [{
    R: { U: 150 }
    }]
}]

我还痛苦地在这里附加了我毫无值(value)的代码,它没有任何作用。

const compare = (p1, p2) => {
  return p1.reduce((acc, curr) => {
    p2.reduce((acc2, curr2) => {
      if (curr.name === curr2.name) {
        const keys1 = R.fromPairs(Object.keys(curr.prop[0]).map(x => ([x, curr.prop[0][x]])));
        const keys2 = R.fromPairs(Object.keys(curr2.prop[0]).map(x => ([x, curr2.prop[0][x]])));
      }
      return acc;
    }, [])

    return acc;
  }, [])
}

如果您有任何帮助和建议,我将非常感激。

最佳答案

所有的困难都在于指定比较函数的预期行为:

对于两个对象(我将其称为值)ab:{A:1,B:2} >{A:1,B:3,C:4} cmp(a,b) 的输出应为:

  foreach key of a:
    if a[key] != b[key] (or b does not have k prop)
      diff[key] = a[key]
    else (value is equal, no diff)
  foreach key of b not in a
    diff[key] = Missing

因此(例如){B:2, C:'Missing'}

比较值时,如果 diff 为空,可以跳过当前 prop;比较 props 时,如果 diff 为空,则跳过记录(就好像名称不同一样)

function cmp(x,y){
  let a = x.prop[0];
  let b = y.prop[0];
  return Object.keys(a).reduce((o,k)=>{
    //compare the right value (such as { A: 1, B: 2 }). assumes primitive types
    let u = a[k];
    let v = b[k];
    
    let diff = Object.keys(u).reduce((o,k)=>{
      return u[k]==v[k]?o:(o[k] = u[k],o)
    },{})
    
    Object.keys(v).reduce((o,k)=>{
      return u.hasOwnProperty(k)?o:(o[k]='Missing',o);
    }, diff);
    
    if(Object.keys(diff).length){
      o[k] = diff;
    }
    
    return o;
  },{});
}
function diff(p1,p2){
  return p1.flatMap((o,i)=>{
    if(p2[i].name != p1[i].name){
      return []
    }

    let a = p1[i];
    let b = p2[i];
    let res = cmp(a,b);
    
    if(!Object.keys(res).length){
      return [];
    }
    
    return {name: a.name, propOne:res, propTwo:cmp(b,a)}
  })
};
const p1 = [{
  name: 'B [1]', // name equals and prop differnce, then comparing it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    C: { C: 78, D: 4, T: 7, } }],
  }, {
  name: 'B [2]', // name equals, then skiping it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, Y: 13 } }],
  }, {
  name: 'B [3]', // name equals and prop differnce, then comparing it
  prop: [{ 
    E: { A: 1, B: 2 }, 
    R: { A: 1, B: 2 }, 
    T: { C: 3,  D: 4, } }],
  }, {
  name: 'B [4]', // name and prop equals, then skiping it 
  prop: [{ 
    A: { A: 1, B: 2 }, 
    S: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, } }],
}]

const p2 = [{
  name: 'B [1]', // name equals and prop differnce, then comparing it 
  prop: [{ 
    A: { A: 1, B: 8 }, 
    B: { A: 1, B: 2 }, 
    C: { C: 3, T: 7, O: 9 } }],
  }, {
  name: 'B [6]', // name not equals, then skiping it
  prop: [{ 
    A: { A: 1, B: 2 }, 
    B: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4 } }],
  }, {
  name: 'B [3]', // name equals and prop differnce, then comparing it
  prop: [{ 
    E: { A: 1, B: 2 }, 
    R: { A: 1, B: 2, U: 150 }, 
    T: { C: 3,  D: 4, } }],
  }, {
  name: 'B [4]', // name and prop equals, then skiping it 
  prop: [{ 
    A: { A: 1, B: 2 }, 
    S: { A: 1, B: 2 }, 
    D: { C: 3,  D: 4, } }],
}];

console.log('result', JSON.stringify(diff(p1,p2),null,2))

关于javascript - 比较两个嵌套数组和对象以查找差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58755725/

相关文章:

algorithm - N皇后问题算法方法的比较

javascript - Yii - 显示/隐藏带有验证的 Div

javascript - 读取查询变量和主体变量有什么区别?

php - 从 PHP 中删除最后一个逗号,该逗号将进入 javascript 图像预加载脚本

algorithm - 堆排序。为什么最坏的情况是最后一棵树的一半?

algorithm - Fortune算法中的断点收敛

javascript - Angular 模态窗口(UI-路由器/指令)

arrays - 如何将数组的元素移动到数组的开头

c - 如何检查指向 char 数组的指针是否指向数字字符?

c++ - Visual Studio C++ |每次我尝试从 [80]x[80] 数组循环 cout 时程序崩溃