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

How does one compare specific key-values within a nested object / array structure?

我有两个数组如下

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

array2 =  {name:"John",surname:"doe",reference:[{name:"jane",surname:"smith,array:[{name:"test",surname:"test",position:12}]"},{name:"kate",surname:"post",array:[{name:"test",surname:"test",position:12}]}],id:"4589632",weight:50,policy:"745896",result:"test",documents:"no",launch:"no"}

如您所见,我的两个数组长度都不匹配,所以我无法比较它们。

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

array1
name:"John"
surname:"doe"
reference:[{name:"jane",surname:"smith",array:[{name:"test",surname:"test",position:12}]},{name:"kate",surname:"post",array:[{name:"test",surname:"test",position:12}]}]
weight:"50"

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

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

如果我有

 array1
    name:"John"
    surname:"doe"
    reference:[{name:"jane",surname:"smith",array:[{name:"test",surname:"test",position:12}]},{name:"kate",surname:"post",array:[{name:"test",surname:"test",position:12}]}]
    weight:"12"

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

以上是错误的。

我怎样才能做到这一点?我怎样才能 filter/loop 通过它们只比较上面提到的值。

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


备注:

  • 我们使用 == 进行比较,因为在您的示例中 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',
  surname: 'doe',
  reference: [{
    name: 'jane',
    surname: 'smith',
  }, {
    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',
  surname: 'doe',
  reference: [{
    name: 'jane',
    surname: 'smith',
  }, {
    name: 'kate',
    surname: 'post',
  }],
  id: '12364',
  weight: '50',
  Oid: '456978',
  code: '12',
}, {
  name: 'John',
  // This value is different
  surname: 'FOOL',
  reference: [{
    name: 'jane',
    surname: 'smith',
  }, {
    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',
  surname: 'doe',
  reference: [{
    name: 'jane',
    surname: 'smith',
  }, {
    name: 'kate',
    surname: 'post',
  }],
  id: '12364',
  weight: '50',
  Oid: '456978',
  code: '12',
}, {
  name: 'John',
  surname: 'doe',
  reference: [{
    name: 'jane',
    // This value is different
    surname: 'FOOL',
  }, {
    name: 'kate',
    surname: 'post',
  }],
  id: '4589632',
  weight: 50,
  policy: '745896',
  result: 'test',
  documents: 'no',
  launch: 'no',
}, [
  'name',
  'surname',
  'reference',
  'weight',
]));

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

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

对于给定的 scenario/example 一个可靠甚至推荐的方法是提供自定义 stringify 函数,该函数 unifies/normalizes 任何提供的对象结构(它们可能不同在对象之间)并清理任何对象的值类型(例如,在 OP 提供的对象示例中有所不同),然后 return 代表这个对象的字符串。

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

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

const objC = {
  name: "John", surname: "doe",
  reference: [{
    name: "jane", surname: "smith", array: [
      { position: 12, surname: "test", name: "test" }
  ]}, {
    name: "kate", surname:"post", array:[
      { name: "test", surname: "test", position: 12 }
    ]
  }],
  weight: "60",
};
const objD = {
  name: "John", surname: "doe",
  reference: [{
    name: "jane", surname: "smith", array: [
      { position: 12, surname: "test", name: "test" }
  ]}, {
    name: "kate", surname:"post", array:[
      { name: "test", surname:"test", position: 24 }
    ]
  }],
  weight: "60",
};

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