Пересечение двух глубоких объектов в JavaScript - PullRequest
0 голосов
/ 28 августа 2018

У меня есть два объекта JavaScript (произвольной глубины), которые имеют большую часть одной и той же информации.

Я ищу помощь получение общих данных между двумя объектами .

Например:

const a = {
  name: 'Alice',
  features: {
    speed: 3,
    strength: 90,
    mind: {
      power: 42
    }
  }
};

const b = {
  name: 'Bob',
  features: {
    speed: 3,
    stamina: 1,
    mind: {
      power: 42,
      flexibility: 0,
      telekinesis: 42
    }
  }
};

Моя цель - найти решение для предоставления данных, которыми они делятся:

const shared = {
  features: {
    speed: 3,
    mind: {
      power: 42
    }
  }
}

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

Это разовая задача, поэтому я не особо беспокоюсь о производительности, и я рад использовать любую библиотеку, пока она работает. Спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

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

Использование переменной temp предотвращает пустые вложенные объекты.

function common(object1, object2) {
    return Object.assign(...Object.keys(object1).map(k => {
        var temp;
        if (!(k in object2)) {
            return {};
        }
        if (object1[k] && typeof object1[k] === 'object' &&
            object2[k] && typeof object2[k] === 'object') {
            temp = common(object1[k], object2[k]);
            return Object.keys(temp).length ? { [k]: temp } : {};
        }
        if (object1[k] === object2[k]) {
           return { [k]: object1[k] };
        }
        return {};
    }));
}

const
    a = { name: 'Alice', features: { speed: 3, strength: 90, mind: { power: 42 } } };
    b = { name: 'Bob', features: { speed: 3, stamina: 1, mind: { power: 42, flexibility: 0, telekinesis: 42 } } };

console.log(common(a, b));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 29 августа 2018

Похоже, что другие ответы в этой теме потерпели крах, когда значение объекта было undefined, поэтому я объединил лучшие части каждого ответа, чтобы найти надежное решение:

const isObj = x => typeof x === 'object'

const common = (a, b) => {
  let result = {}

  if (([a, b]).every(isObj)) {
    Object.keys(a).forEach((key) => {
      const value = a[key]
      const other = b[key]

      if (isObj(value)) {
        result[key] = common(value, other)
      } else if (value === other) {
        result[key] = value
      }
    })
  }

  return result
}
0 голосов
/ 28 августа 2018

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

const a = {
  name: 'Alice',
  features: {
    speed: 3,
    strength: 90,
    mind: {
      power: 42
    }
  }
};

const b = {
  name: 'Bob',
  features: {
    speed: 3,
    stamina: 1,
    mind: {
      power: 42,
      flexibility: 0,
      telekinesis: 42
    }
  }
};

function equalProps(a,b){
  var newObj = {}; 
  for (var key in a){
    if (typeof a[key] === 'object'){
      var obj = equalProps(a[key], b[key]);
      newObj[key] = obj;
    }else if (a[key] == b[key]){
      newObj[key] = a[key];
    }
  }
  return newObj;
}

console.log(equalProps(a,b))
...