2015-06-28 4 views
1

Я пытаюсь написать функцию, которая проверяет, имеют ли два объекта одинаковые значения. Эта функция требует проверки равенства любых объектов, которые хранятся как значения внутри исходных объектов. Подход, который я разработал (см. Код ниже), - это сначала проверить равенство значений, отличных от объекта. Затем, если все они совпадают, я снова перебираю объекты и делаю рекурсивный вызов исходной функции, что позволяет мне сравнивать каждый вложенный уровень этих двух объектов.Проверка функции для «глубокого равенства» вложенных объектов

Однако этот подход работает только частично. Характер рекурсивного вызова означает, что я могу проверить равенство вложенных объектов в первой паре ключ-значение в объекте. Я не могу понять, как проверить любые дополнительные пары ключ-значение, содержащие вложенные объекты, когда первый набор вложенных объектов сравнивается, и возвращается рекурсивный вызов. Вот функция:

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

Вы говорите, что вам не нужны имена собственности? Btw, 'для (i в val1) для (i в val2)' является катастрофическим. – Bergi

+0

Я проверяю значения. Согласитесь, что петли for не оптимальны - несите меня, я неопытный программист, это был мой первый проход по этой проблеме. – benpiggot

+0

Итак, вы ожидали бы '{a: 1, b: 2}' и '{a: 2 , b: 1} 'равны (поскольку они содержат одни и те же значения)? – Bergi

ответ

0

Простым решением было бы JSON подкрепить объекты и сравнить их представления строк. Как @Jan упоминает ...

это будет работать, только если объекты инициализируются в том же способом. Если свойства одинаковы, но в другом порядке, он будет неудачу

... это немного хрупким, но может удовлетворить ваши цели.

1

Вот одно из возможных решений, но я рекомендую вам найти свое.

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)) 
+0

Спасибо за это - инструкция, которую я имел для проблемы, заключалась в том, чтобы сделать это в одной функции, но это определенно имеет смысл. Спасибо за вашу работу! – benpiggot

+0

Какая ужасная инструкция ... Это не то, что вы хотите закодировать, да. – Jan

1

То, что вы, вероятно, хотите, _.isEqual из библиотеки lodash или underscore.

Существует также тест deepEqual из библиотеки утверждений Chai.js.

Смежные вопросы