如何比较嵌套对象/数组结构中的特定键值?

问题描述

我有两个数组如下

array1 = {name:"John",surname:"doe",reference:[{name:"jane",surname:"smith",array:[{name:"test",surname:"test",position:12}]},{name:"kate",surname:"post",position:12}]}],id:"12364",weight:"50",Oid:"456978",code:"12"}

array2 =  {name:"John",surname:"smith,position:12}]"},id:"4589632",weight:50,policy:"745896",result:"test",documents:"no",launch:"no"}

正如你所看到的,我的两个数组长度都不匹配,所以我无法比较它们。

我只想比较数组 1 和数组 2 中的某些对象。 例如只有我需要的对象

array1
name:"John"
surname:"doe"
reference:[{name:"jane",position:12}]}]
weight:"50"

array 2
name:"John"
surname:"doe"
reference:[{name:"jane",position:12}]}]
weight:50

我只想比较上面的对象键值,所以上面的会返回true

如果我有

 array1
    name:"John"
    surname:"doe"
    reference:[{name:"jane",position:12}]}]
    weight:"12"

array 2
name:"John"
surname:"Petter"
reference:[{name:"jane",surname:"t2",surname:"Knight",position:14}]}]
weight:50

以上都是假的。

我怎样才能做到这一点?我如何过滤/循环它们以仅比较上述值。

解决方法

您可以创建一个函数来进行检查。


注意事项:

  • 我们使用 == 进行比较,因为在您的示例中,weight: 50 将等于 weight: '50'(字符串和数字)。
  • 该函数还使用相同的键比较内部数组 reference

function compareObjects(obj1,obj2,keysToCompare) {
  return keysToCompare.every(x => obj1[x] instanceof Array ?
    obj1[x].every((y,yi) => compareObjects(y,obj2[x][yi],Object.keys(y))) :
    obj1[x] == obj2[x]);
}

// Nothing is different - should work
console.log(compareObjects({
  name: 'John',surname: 'doe',reference: [{
      name: 'jane',surname: 'smith',},{
      name: 'kate',surname: 'post'
    },],id: '12364',weight: '50',Oid: '456978',code: '12',{
  name: 'John',reference: [{
    name: 'jane',{
    name: 'kate',surname: 'post',}],id: '4589632',weight: 50,policy: '745896',result: 'test',documents: 'no',launch: 'no',[
  'name','surname','reference','weight',]));

// One key is different - should fail
console.log(compareObjects({
  name: 'John',// This value is different
  surname: 'FOOL',// This value is different
    surname: 'FOOL',]));

// Position is different - should work
console.log(compareObjects({
  name: 'John',position: 10,position: 15,]));

// Everything is same - should work (including position)
console.log(compareObjects({
  name: 'John',]));

,

对于给定的场景/示例,一个可靠甚至推荐的方法是提供一个自定义的 stringify 函数,该函数统一/规范化任何提供的对象结构(它们可能因对象而异)并且还清理任何对象的值类型(例如,在 OP 提供的对象示例之间确实有所不同),然后确实返回代表该对象的字符串。

以这种方式处理的对象可以安全地相互比较......

const objA = {
  name: "John",surname: "doe",reference: [{
    name: "jane",surname: "smith",array: [
      { position: 12,surname: "test",name: "test" }
    ]
  },{
    name: "kate",surname:"post",array:[
      { name: "test",position: 12 }
    ]
  }],id: "12364",weight: "50",Oid: "456978",code: "12",};
const objB = {
  reference: [{
    surname:"post",name: "kate",position: 12 }
    ]
  },{
    array: [
      { name: "test",position: 12 }
    ],name: "jane",name: "John",id: "4589632",policy: "745896",result: "test",documents: "no",launch: "no",};

const objC = {
  name: "John",name: "test" }
  ]},weight: "60",};
const objD = {
  name: "John",surname:"test",position: 24 }
    ]
  }],};

const orderByName = (a,b) =>
  a.surname.localeCompare(b.surname) || a.name.localeCompare(b.name);

function normalizeItemReference(arr) {
  return arr
    // assure a certain order.
    .sort(orderByName)
    // assure identical structure. 
    .map(({ name,surname,array }) =>
      ({
        name,array: array
          // assure a certain order.
          .sort(orderByName)
          // assure identical structure and value type.
          .map(({ name,position }) =>
            ({ name,position: Number(position) })
          )
      })
    );
}
function stringifyItem(obj) {
  const { name,weight,reference } = obj;
  return JSON.stringify({
    // assure identical structure and value types.
    name,weight: Number(weight),reference: normalizeItemReference(reference)
  });
}

console.log(
  '(stringifyItem(objA) === stringifyItem(objB)) ?',(stringifyItem(objA) === stringifyItem(objB))
);
console.log(
  '(stringifyItem(objA) === stringifyItem(objC)) ?',(stringifyItem(objA) === stringifyItem(objC))
);
console.log(
  '(stringifyItem(objC) === stringifyItem(objD)) ?',(stringifyItem(objC) === stringifyItem(objD))
);

console.log(
  'stringifyItem(objA) ...',stringifyItem(objA)
);
console.log(
  'stringifyItem(objB) ...',stringifyItem(objB)
);
console.log(
  'stringifyItem(objC) ...',stringifyItem(objC)
);
console.log(
  'stringifyItem(objD) ...',stringifyItem(objD)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }