Home > database >  How to dynamically append key/values to a nested object
How to dynamically append key/values to a nested object

Time:12-30

I am trying to append to an object/dictionary of sorts that adds categories and subcategories as they are found. However, each time I try to add them it seems like I just get the last element added to the nested object and overwrites the previous additions. I've tried using Object.assign() and {...obj, key:value} to no avail.

I have multiple for-loops that independently add each key:value pair after the database has been queried.

I am looking to create an object resembling this:

{
  category1: {
    subcategory1: null,
    subcategory2: null,
    subcategory3: {
      microcategory1: null
    }
  },
  category2: {
    subcategory1: null,
    subcategory2: null,
    subcategory3: null
  }
}

But am getting this instead:

{
  cooking: {
    'ranges': null
  },
  sinks: {
    'filters': null
  }
}

There should be 10 subcategories for both cooking and sinks.

This is the code as it stands:

let categoriesDictObj = {};

for (var index = 0; index < categories.length; index  ) {
  let category = categories[index];

  const subCategories = await Product.find({
    productCategory: category,
  }).distinct("productSubCategory");

  for (
    var subCatIndex = 0; subCatIndex < subCategories.length; subCatIndex  
  ) {
    let subCategory = subCategories[subCatIndex];

    const microCategories = await Product.find({
      productMicroCategory: subCategory,
    }).distinct("productMicroCategory");


    // categoriesDictObj[category] = { [subCategory]: null };

    // Object.assign(categoriesDictObj, {
    //   [category]: { [subCategory]: null },
    // });

    categoriesDictObj = {
      ...categoriesDictObj,
      [category]: {
        [subCategory]: subCatIndex
      },
    };
  }
}

CodePudding user response:

You're missing to spread the previous categoriesDictObj[category] in the inner object, otherwise you're always overwriting the category object with a completely new one and only the last (with a single subCategory key) will prevail.

categoriesDictObj = {
  ...categoriesDictObj,
  [category]: {
    ...categoriesDictObj[category],
    [subCategory]: subCatIndex
  },
};

However, there's no need to make it that complicated. Just create the inner object, fill it in the inner loop, and then assign it as part of the categoriesDictObj in the outer loop:

const categories = …;
const categoriesDictObj = {};

for (let index = 0; index < categories.length; index  ) {
  const category = categories[index];
  const subCategories = …;

  const subCategoriesDictObj = {};
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  for (let subCatIndex = 0; subCatIndex < subCategories.length; subCatIndex  ) {
    const subCategory = subCategories[subCatIndex];
    const microCategories = …;

    subCategoriesDictObj[subCategory] = subCatIndex;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  }
  categoriesDictObj[category] = subCategoriesDictObj;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

You could also make the variables mutable and keep the objects immutable by replacing the subCategoriesDictObj[subCategory] assignment with

subCategoriesDictObj = {
  ...subCategoriesDictObj,
  [subCategory]: subCatIndex
};

and the categoriesDictObj[category] asssignment with

categoriesDictObj = {
  ...categoriesDictObj,
  [category]: subCategoriesDictObj
};

but that's really just pointless inefficiency.

  • Related