Проверка функций на "глубокое равенство" вложенных объектов
Я пытаюсь написать функцию, которая проверяет, имеют ли два объекта одинаковые значения. Эта функция требует, чтобы я проверял равенство любых объектов, которые хранятся как значения внутри исходных объектов. Подход, который я разработал (см. Код ниже), заключается в том, чтобы сначала проверить равенство необъектных значений. Затем, если все они совпадают, я снова перебираю объекты и выполняю рекурсивный вызов исходной функции, что позволяет мне сравнивать каждый вложенный уровень двух объектов.
Однако этот подход работает только частично. Природа рекурсивного вызова означает, что я могу проверить только равенство вложенных объектов в первой паре ключ-значение в объекте. Я не могу понять, как проверить какие-либо дополнительные пары ключ-значение, содержащие вложенные объекты, после сравнения первого набора вложенных объектов и возврата рекурсивного вызова. Вот функция:
var deepEqual = function(val1, val2) {
if (typeof val1 === 'object' && typeof val2 === 'object') {
for (i in val1) {
for (i in val2){
if (typeof val1[i] !== 'object' && typeof val2[i] !== 'object') {
if (val1[i] !== val2[i]) {
return false
}
}
}
}
for (i in val1) {
for (i in val2){
if (typeof val1[i] === 'object' && typeof val2[i] === 'object') {
return deepEqual(val1[i], val2[i])
}
}
}
return true
}
else if (val1 === val2) {
return true
}
else return false
}
Моя основная проблема в том, что я считаю, что мне нужен рекурсивный вызов для проверки глубокого равенства вложенных объектов, но я могу выполнить эту проверку только один раз. Кто-нибудь пытался решить такую проблему? Я приведу примеры моих результатов для конкретных объектов, если вам нужно более конкретное. Спасибо!
3 ответа
Простое решение состоит в том, чтобы JSON структурировал объекты и сравнил их строковые представления. Как @Jan упоминает...
это будет работать, только если объекты инициализируются точно так же. Если свойства одинаковы, но в другом порядке, произойдет сбой
... это немного ломко, но может удовлетворить ваши цели.
Вот одно из возможных решений, но я действительно рекомендую найти свое.
function isEqual(var1, var2) { // Break the comparison out into a neat little function
if (typeof var1 !== "object") {
return var1===var2;
} else {
return deepEqual(var1, var2);
}
}
function deepEqual(var1, var2) {
for (i in var1) {
if(typeof var2[i] === "undefined") { // Quick check, does the property even exist?
return false;
}
if (!isEqual(var1[i], var2[i])) {
return false;
}
}
return true;
}
function areObjectsEqual(obj1, obj2) {
return deepEqual(obj1, obj2) && deepEqual(obj2, obj1); // Two-way checking
}
Вам нужно не только проверить, все ли в obj1
существует в obj2
но и то, что все в obj2
существует в obj1
, Это решение предполагает сравнение в обоих направлениях, но вы могли бы значительно оптимизировать это.
И некоторые тесты
var v1 = { obj0:"jan", obj:{ name:"jan"}, obj2:"ben" }
var v2 = { obj:{ name:"jan"}, obj2:"ben" }
console.log(areObjectsEqual(v1, v2))
v1 = { obj:{ name:"jan"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben" }
console.log(areObjectsEqual(v1, v2))
v1 = { obj:{ name:"jan2"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben" }
console.log(areObjectsEqual(v1, v2))
v1 = { obj:{ name:"jan"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben", obj3:"pig" }
console.log(areObjectsEqual(v1, v2))
То, что вы, вероятно, хотите _.isEqual
от lodash
или же underscore
библиотека.
Также есть deepEqual
тест из Chai.js
библиотека утверждений.