Сравнение объектов JS

Помогите, пожалуйста, найти ошибку, не срабатывает код для сравнения объектов:
function objEqual(a, b) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);

for (var i = 0; i < keysA.length; i++) {
var key = keysA[i];
if (key in keysB)
return true;
}
return keysA.length !== keysB.length;
}

Благодарю за помощь!

Привет!
Чтобы просто код запускался, то вот, там фигурных скобок парочки не хватало:

function objEqual(a, b) {
  var keysA = Object.keys(a);
  var keysB = Object.keys(b);

  for (var i = 0; i < keysA.length; i++) {
    var key = keysA[i];
    if (key in keysB) {
      return true;
    }
  }
  return keysA.length !== keysB.length;
}

Форматируй код - поможет находить такие ошибки.

А по поводу написания функции для сравнения объектов попробую повдохновляться готовыми решениями (если стоит задача написать свою такую функцию). Вот например обсуждение: How can I determine equality for two JavaScript objects?. Ну, или прикинуть свой алгоритм. В очень упрощенном виде, на основе твоего код:

function objEqual(a, b) {
  var keysA = Object.keys(a);
  var keysB = Object.keys(b);

  if (keysA.length !== keysB.length) {
      return false
  }
    
  for (var i = 0; i < keysA.length; i++) {
    var key = keysA[i];
    if (!keysB.includes(key) || a[key] !== b[key]) {
      return false;
    }
  }

  return true  
}

Там надо его дополнять, проверять какой тип поля объекта, например если это массив, то сравнивать поочередно все элементы массива, если тип поля объект - то рекурсивно вызывать саму функцию сравнения objEqual(). Нужно сделать сложных тестов и на основе этих тестов проверять и дорабатывать эту функцию сравнения objEqual(). Типа:

const a = {
  a: 1,
  b: [1, 2, 3]
  c: {
    d: 4,
    e: 'f'
  }
};

const b = {
  a: 1,
  b: [1, 2, 3]
  c: {
    d: 4,
    e: 'k'
  }
}
objEqual(a, b);

И дальше придумывать свои различные простые и сложные объекты a и b и допиливать и рихтовать на их основе функцию сравнения, как-то так.

2 лайка

СПАСИБО за помощь!!!

1 лайк

Если не затруднит, подскажите еще, что не учитывается для успешного прохождения тестов для сравнения (у меня пара тестов проваливается):

function objEqual(a, b) {
  var keysA = Object.keys(a);
  var keysB = Object.keys(b);

  for (var i = 0; i < keysA.length; i++) {
    var key = keysA[i];
    if (key in keysB) {
      return true;
    }
  }
  if (keysA.length !== keysB.length) {
    return false;
  } else {
    return true;
  }
}
   function deepEqualTests() {
    
    var H1={ a:5, b: { b1:6, b2:7 } };
    var H2={ b: { b1:6, b2:7 }, a:5 };
    var H3={ a:5, b: { b1:6 } };
    var H4={ a:5, b: { b1:66, b2:7 } };
    var H5={ a:5, b: { b1:6, b2:7, b3:8 } };
    var H6={ a:null, b:undefined, c:Number.NaN };
    var H7={ c:Number.NaN, b:undefined, a:null };

   console.log( (H1 === H2)?'пройден':'НЕ ПРОЙДЕН!' );   // => true
   console.log( (H1 !== H3)?'пройден':'НЕ ПРОЙДЕН!' ); // => false
   console.log( (H1 !== H4)?'пройден':'НЕ ПРОЙДЕН!' );  //  => false
   console.log( (H1 !== H5)?'пройден':'НЕ ПРОЙДЕН!' ); //  => false
   console.log( (H6 === H7)?'пройден':'НЕ ПРОЙДЕН!' ); //  => true  
 }

Не учитывается порядок расположения ключей в объекте? как лучше эти случаи исправить?

Причина в другом.

Во-первых задача (которая поставленна как “что не так с реализацией”) которую тебе нужно решить чисто “механическая”. Для поиска причины падающих тестов достаточно выполнить ряд действий. Именно эти действия и проделают люди которые дадут ответ на твой вопрос. А значит ты можешь проделать эти действия самостоятельно (но не так эффективно как те кто повторял их сотни-тыщи раз):

  1. Иметь реализацию (она у тебя есть) решения.
  2. Иметь такой ввод (инпут, входные данные) для которых реализация не возвращает желаемого результата. Это тоже есть: те параметры для которых “падают” тесты
  3. Пройти по каждому шагу реализации с данными из шага 2 чтобы найти то место которое работает не так как ожидается. Ведь какой-то кусок кода отвечает за то что непохожие объекты посчитались похожими.

Шаг 3 можно делать и через debugger и через расстановку стратегических console.log.


По поводу самой реализации.

  1. Я не вижу кода который бы отвечал за сравнение значений в ключах объекта. Я вижу только сравнения ключей но не значений за ними.
  2. Скорее всего решение должно быть рекурсивным (следует из названия deepEqualTes), так как значения в ключах объекта могут сами содержать объекты.
if (key in keysB) {
      return true;
    }

Очень похоже что ты имеешь в виду в этих строках что-то типа “если значение в переменной key включено в массив, то верни true”. Во-первых вхождение в массив делается не через оператор in, во вторых этот return слишком ранний так как он сработает для всей функции, не проверяя других ключей (считай будет достаточно наличия одного ключа в обоих объектах чтобы сравнение на равенство объектоа дало true, но это же недостаточно условие равенства).


Тебе нужно пересмотреть реализацию с самого начала. В ней есть рабочие элементы (как то сравнение количества ключей), но их недостаточно для рабочего решения.

Общая стратегия для решения (могу упустить нюансы, но надеюсь суть передам):

  1. На входе функции решения (назовем ее isDeeplyEqual - ) два значения. Если это примитивные значения, то функция вернет равенство если они равны. Иначе значения не примитивны (массивы или объекты)
  2. Если непримитивные зачения разного типа, значит они не равны
  3. Если они одного типа, то
    3.1 Для массивов все элементы одного должны быть равны всем элементам второго, для чего используем рекурсивный вызов isDeeplyEqual с аргументами с одинаковым индексом из каждого из массивов
    3.2 Для объектов.
    3.2.1. Если количество и значения ключей не совпадает то объекты не равны
    3.2.2. Используем рекурсивный isDeeplyEqual для сравнения значений под одинаковыми ключами в этих двух объектах.
1 лайк