Разбор, пересчет вложенных объектов

  • есть объект продукта
  • в нем компоненты, из которых состоит продукт
  • компоненты представлены в виде вложенных объектов
  • компонент может быть простым или комплексным
  • для простых компонентов и комплексных (первого уровня вложенности) указано необходимое количество для создания продукта
  • у комплексных компонентов есть пустой объект, который должен быть заполнен в процессе разбора вложенных
let product = {
    'VOP': { complex: true, count: 51, consist: {} },
    'gem': { complex: false, count: 2 }
}
  • есть объект комплексных компонентов
  • комплексные компоненты содержат простые и комплексные (N-вложенность)
  • для вложенных компонентов указано количество, необходимое для создания одного компонента, в составе которого он находится
let complexRes = {
    'VOP': {
        'vrs': { complex: false, count: 3 },
        'sop': { complex: false, count: 1 },
        'CBP': { complex: true, count: 3, consist: { } }
    },
    'CBP': {
        'ab': { complex: false, count: 10 }
    }
}
  • Нужно сделать пересчет количества вложенных компонентов и модифицировать объект product
  • В резльтате должны получить такое:
product = {
    'VOP': { complex: true, count: 51, consist: {
        'vrs': { complex: false, count: 153 },
        'sop': { complex: false, count: 51 },
        'CBP': { complex: true, count: 153, consist: {
            'ab': { complex: false, count: 1530 }
        } }
      } },
    'gem': { complex: false, count: 2 }
}

Пробовал делать в таком духе, но запутался


let complexConsist = {}

for(let key in product) {
    if(product[key]['complex']){
        calc(key, product[key]);
    }
}

function calc(key, obj) {
    complexConsist[key] = JSON.parse(JSON.stringify(obj));
    for(let keyInner in complexRes[key]) {
        if(complexRes[key][keyInner]['complex']) {
            
            // дальше запутался, наговнокодил, выкладывать нет смысла видимо )
        }
    }
}

Может кто понял, что требуется и поможет дописать? )

UPD: вариант посложнее:

const complexResInit = {
  'VOP': {
    'vrs': { complex: false, count: 3 },
    'sop': { complex: false, count: 1 },
    'CBP': { complex: true, count: 3, consist: { } }
  },
  'CBP': {
    'ab': { complex: false, count: 10 }
  },
  'MM': {
    'mold': { complex: false, count: 10 },
    'VOP': { complex: true, count: 10, consist: { } }
  }
}

const productInit = {
  'VOP': { complex: true, count: 51, consist: {} },
  'gem': { complex: false, count: 2 },
  'MM': { complex: true, count: 1, consist: {} } 
}


Ответы (1 шт):

Автор решения: SwaD

Для обхода однотипных многоуровневых объектов используют рекурсию

const complexResInit = {
  'VOP': {
    'vrs': { complex: false, count: 3 },
    'sop': { complex: false, count: 1 },
    'CBP': { complex: true, count: 3, consist: { } }
  },
  'CBP': {
    'ab': { complex: false, count: 10 }
  },
  'MM': {
    'mold': { complex: false, count: 10 },
    'VOP': { complex: true, count: 10, consist: { } }
  }
}

const productInit = {
  'VOP': { complex: true, count: 51, consist: {} },
  'gem': { complex: false, count: 2 },
  'MM': { complex: true, count: 1, consist: {} } 
}

function compareProducts(product, complexRes, multiplier = 1) {
  const res = {};
  for(let key in product) {
    res[key] = { ...product[key] };
    res[key].count *= multiplier;
    if (product[key].complex) res[key].consist = compareProducts(complexRes[key], complexRes, res[key].count)
  }
  return res;
}

const result = compareProducts(productInit, complexResInit)
console.log(result);

Для правильного составления рекурсивного обхода, надо понять, по каким признакам определять, что надо запустить рекурсию и что передавать на следующую итерацию.

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

Еще пример рекурсии "на массивах":

function compareProductsArray(product, complexRes, multiplier = 1) {
  return Object.entries(product).reduce((acc, [key, val]) => {
    acc[key] = { ...val };
    acc[key].count *= multiplier;
    if (val.complex) acc[key].consist = compareProductsArray(complexRes[key], complexRes, acc[key].count);
    return acc;
  }, {});
}
→ Ссылка