Home > Net >  Create array of arrays of objects with var names
Create array of arrays of objects with var names

Time:10-27

Here is my problem:

const data : [
{labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
{labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
{labelSlug: 'fanta', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},{labelSlug: 'activities1', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla'},
{labelSlug: 'activities2', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla'},
{labelSlug: 'equipments1', category: 'equipments', subCategory: 'equipmentsSub1', provider: 'blabla'},
{labelSlug: 'equipments2', category: 'equipments', subCategory: 'equipmentsSub2', provider: 'blabla'}
{labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
]

I'm trying to get something like this for each category and subCategory:

{
  catering : [
    drinks : [
      { labelSlug: cola, provider: coca cola, count: 3 },
      { labelSlug: fanta, provider: coca cola, count: 1 }
    ]
  ]
}

The problem is I don't know how to set up this, I've tried all I could do:

const array = data.map((elem) => {
  const item = {};
  const sub = elem.subCategory;
  const cat = elem.category;

  // i've tried many things like that just to get everything in the right place (I didnt try to get the count part yet)
  // item[cat[sub]].labelSlug = elem.labelSlug;
  // item[cat][sub].labelSlug = elem.labelSlug;
  // item[cat[sub.labelSlug]] = elem.labelSlug;

  // const item = {
  //   [`${cat}`] : {
  //      [`${sub}`] : {
  //        labelSlug: elem.labelSlug
  //      } 
  //   }
  // }
  return item;
})

CodePudding user response:

Assuming you want to group the items by their labelSlug and all the other properties will be the same if the labelSlug is the same:

  1. Create an empty object
  2. Iterate over the array:
  3. Create any missing objects/arrays
  4. Find or create the object (with count 0 by default)
  5. Increase count
  6. Repeat
const result = {}

for (const { category, subCategory, ...properties } of data) {
  result[category] ??= {}
  result[category][subCategory] ??= []
  const items = result[category][subCategory]

  let item = items.find(o => o.labelSlug === properties.labelSlug)
  if (!item) {
    item = { ...properties, count: 0 }
    items.push(item)
  }

  item.count  
}

Here you can see it in action:

const data = [{
    labelSlug: 'cola',
    category: 'catering',
    subCategory: 'drinks',
    provider: 'coca cola'
  },
  {
    labelSlug: 'cola',
    category: 'catering',
    subCategory: 'drinks',
    provider: 'coca cola'
  },
  {
    labelSlug: 'fanta',
    category: 'catering',
    subCategory: 'drinks',
    provider: 'coca cola'
  }, {
    labelSlug: 'activities1',
    category: 'activities',
    subCategory: 'activitiesSub1',
    provider: 'blabla'
  },
  {
    labelSlug: 'activities2',
    category: 'activities',
    subCategory: 'activitiesSub1',
    provider: 'blabla'
  },
  {
    labelSlug: 'equipments1',
    category: 'equipments',
    subCategory: 'equipmentsSub1',
    provider: 'blabla'
  },
  {
    labelSlug: 'equipments2',
    category: 'equipments',
    subCategory: 'equipmentsSub2',
    provider: 'blabla'
  },
  {
    labelSlug: 'cola',
    category: 'catering',
    subCategory: 'drinks',
    provider: 'coca cola'
  },
]

const result = {}

for (const { category, subCategory, ...properties } of data) {
  result[category] ??= {}
  result[category][subCategory] ??= []
  const items = result[category][subCategory]

  let item = items.find(o => o.labelSlug === properties.labelSlug)
  if (!item) {
    item = { ...properties, count: 0 }
    items.push(item)
  }

  item.count  
}

console.log(result)

CodePudding user response:

To achieve the desired results, you'll need a more complex restructure of the result than what is possible with a simple map call (as this new structure will not be 1 to 1 mappeable with the current input)

const data = [
    { labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola' },
    { labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola' },
    { labelSlug: 'fanta', category: 'catering', subCategory: 'drinks', provider: 'coca cola' }, { labelSlug: 'activities1', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla' },
    { labelSlug: 'activities2', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla' },
    { labelSlug: 'equipments1', category: 'equipments', subCategory: 'equipmentsSub1', provider: 'blabla' },
    { labelSlug: 'equipments2', category: 'equipments', subCategory: 'equipmentsSub2', provider: 'blabla' },
    { labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola' }
]


const dict = {}

for(entry of data) {
    const { labelSlug, category, subCategory, provider } = entry
    dict[category] = dict[category] || {}
    dict[category][subCategory] = dict[category][subCategory] || []
    
    let item = { labelSlug, provider, count: 1 }
    const index = dict[category][subCategory].findIndex(e => e.labelSlug === labelSlug && e.provider === provider)

    if(index > -1) {
        dict[category][subCategory][index].count  
    }
    else {
        dict[category][subCategory].push(item)
    }
}

console.log(dict)

CodePudding user response:

Check out JavaScripts's Array.reduce() method! It's kind of like the swiss army knife of array methods and you can use it to reduce or "transform" your array of objects into whatever you like!

const data = [
  {labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
  {labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
  {labelSlug: 'fanta', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
  {labelSlug: 'activities1', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla'},
  {labelSlug: 'activities2', category: 'activities', subCategory: 'activitiesSub1', provider: 'blabla'},
  {labelSlug: 'equipments1', category: 'equipments', subCategory: 'equipmentsSub1', provider: 'blabla'},
  {labelSlug: 'equipments2', category: 'equipments', subCategory: 'equipmentsSub2', provider: 'blabla'},
  {labelSlug: 'cola', category: 'catering', subCategory: 'drinks', provider: 'coca cola'},
]

const organizedData = data.reduce((obj, curr) => {
  // the current item we're on in the loop
  const { category, subCategory, ...restOfData } = curr

  // if our accumulator obj has the category key and that obj[category] has the subcategory key
  category in obj && subCategory in obj[category]
    // if so, let's push our data to the subcategory array
    ? obj[category][subCategory].push(restOfData)
    // if obj does not have the category to begin with...
    // lets set a category key on the object with a starting and assign a subCategory key and array of items as the value
    : obj[category] = { [subCategory]: [restOfData] }

  return obj // must return the accumulator for each iteration of the loop to be used in the next run
}, {}) 

console.log(organizedData)

/* Result:
{
  "catering": {
    "drinks": [
      {
        "labelSlug": "cola",
        "provider": "coca cola"
      },
      {
        "labelSlug": "cola",
        "provider": "coca cola"
      },
      {
        "labelSlug": "fanta",
        "provider": "coca cola"
      },
      {
        "labelSlug": "cola",
        "provider": "coca cola"
      }
    ]
  },
  "activities": {
    "activitiesSub1": [
      {
        "labelSlug": "activities1",
        "provider": "blabla"
      },
      {
        "labelSlug": "activities2",
        "provider": "blabla"
      }
    ]
  },
  "equipments": {
    "equipmentsSub2": [
      {
        "labelSlug": "equipments2",
        "provider": "blabla"
      }
    ]
  }
}
*/

  • Related