Generate an array of arrays containing objects using different variable names

Here is the issue at hand:

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 am attempting to achieve a structure like this for each category and subCategory:

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

The challenge lies in figuring out how to configure this setup, I have exhausted all possible approaches:

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;
})

Answer №1

To achieve the desired outcome, a more intricate restructuring of the data is required. A simple map function will not suffice as the new structure does not directly correspond to the current input.

const dataset = [
    { 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 reference = {}

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

    if(idx > -1) {
        reference[category][subCategory][idx].count++
    }
    else {
        reference[category][subCategory].push(item)
    }
}

console.log(reference)

Answer №2

Suppose you aim to categorize items based on their labelSlug, where all other attributes remain consistent if the labelSlug matches:

  1. Initialize an empty object
  2. Loop through the array:
  3. Create any missing objects/arrays
  4. Locate or create the object (with a default count of 0)
  5. Increment the count
  6. Repeat the process
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++
}

See the code in action below:

const data = [{
    labelSlug: 'cola',
    category: 'catering',
    subCategory: 'drinks',
    provider: 'coca cola'
  },
  // Additional data entries here...
]

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)

Answer №3

Discover the versatility of JavaScript's Array.reduce() method! This powerful tool functions like a swiss army knife for array manipulation, allowing you to transform your array of objects in various ways.

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: '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) => {
  // current item being iterated over
  const { category, subCategory, ...restOfData } = curr
  
  if (category in obj && subCategory in obj[category]) {
    const matchIdx = obj[category][subCategory].findIndex(o => o.labelSlug === restOfData.labelSlug)
    if (matchIdx > -1) {
      obj[category][subCategory][matchIdx].count++
    } else {
      obj[category][subCategory].push({ ...restOfData, count: 1 })
    }
  } 
  else {
    obj[category] = { 
      [subCategory]: [{ ...restOfData, count: 1 }],
    }
  }

  return obj 
}, {}) 

console.log(organizedData)

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

Updated response to incorporate duplicate values with a dups count.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Modifying Div Size with Jquery

I am working on populating the div container with square boxes, but I'm having trouble adjusting the size of my #gridSquare div. Despite trying to change its height and width using jQuery, it doesn't seem to work as expected. $('#gridSquare ...

The Nuxt authentication middleware fails to function properly upon clicking the back button in the browser

When it comes to implementing the protected route in Nuxt, I have found that using middleware is the best approach. In my implementation, I utilized the cookie-universal-nuxt module. Everything was running smoothly until I encountered a bug. When a user&a ...

How can I ensure that the elements inside the '.box' are responsive, including dropdown buttons, text, and more?

I have successfully made my banner/header responsive, and I placed the dropdown buttons inside a box. I am new to bootstrap and pretty much new to everything, so I just copied some codes from demos. I need help making this specific box responsive along wit ...

How to style date strings in JavaScript, jQuery, or CSS

Below are dates that need formatting: 7-sep, 14-sep, 21-sep, 28-sep, 5-oct,12-oct, 19-oct,26-oct, 2-nov, 9-nov, 16-nov, 23-nov,30-nov, 7-dec,14-dec, 21-dec,28-dec-2013. Is there a way to tidy them up using JavaScript, jQuery, or CSS? Ideally, I would lik ...

Is it possible to compare two charts in Chart.js in a way that avoids the issue of small values appearing as large as big values?

I am currently working on a production tracking page that features multiple charts. I want to avoid inconsistencies in tracking at first glance. Is there a way to achieve this using chart.js? If not, what would be the best approach to address this issue? ...

What is the best way to structure a data object in Javascript or VueJs?

As I work on developing a small application using VueJs, the data I receive is structured in a particular format: { "interactions":[ { "id":14, "user_id":1, "schedule":"2017-06-04 05:02:12", "typ ...

What is the best way to incorporate lottiefiles for a loading animation on a Next.js project's landing

Is there a way to incorporate the use of lottie in a Next.js project (App Structure) in order to load an animated logo seamlessly? I attempted to include "use client" without success, and also tried importing Lottie from react-lottie as a dynamic import. ...

"Obtaining a MEAN response after performing an HTTP GET

I'm currently in the process of setting up a MEAN app, however I've hit a roadblock when it comes to extracting data from a webservice into my application. While returning a basic variable poses no issue, I am unsure how to retrieve the result fr ...

Move the Form to the Top of the Window and Highlight the First Input Field

There's a link in the header that says "Let's chat": <div class="letstalk"> <a href="javascript:scrollForm();"> Let's chat <img src="/wp-content/uploads/link-icon.png"> </a> </div> ...

Retrieving information from an Angular service using a specified function

I have been working on accessing data from a method within a service that returns coordinates, which are used to make HTTP requests in my application. I have integrated my Leaflet code into the controller to be able to access the lat,lng coordinates for ...

What is the best way to rephrase a sentence that contains a double negative

Figuring out how to negate a condition often requires hours of trial and error to avoid breaking anything. Is there any method for negating conditions other than relying on intuition? For instance: //x and y are whole numbers !((x<9) && (y&l ...

Would it be beneficial to upload and download an image using the same ajax call?

I recently made a change to my web app's image upload feature. Previously, the process involved uploading an image, retrieving the image URL, and then making a second request to download the image from the URL. Now, I have streamlined it so that when ...

Learning the process of obtaining tags through the utilization of the tag-it jQuery plugin

I'm currently using the tag-it jQuery plugin for a project I'm working on. However, I am facing an issue where I am unable to retrieve the tags that were entered in the text area as I keep getting an empty string. Here is the code snippet I am wo ...

Displaying tooltips dynamically for newly added elements all sharing a common class in React

I'm facing an issue with the primereact tooltip component from . Everything seems to be working fine except for the target property. When I have multiple elements on a page with the same class, the tooltip works as expected. However, when I add a new ...

Learn how to extract data from the "this" object in JavaScript

Can anyone help me with retrieving the numbers generated by this code snippet? $("#100wattaren") .countdown("2018/01/01", function(event) { $(this).text( event.strftime('%D days %H hours %M minutes %S seconds') ); }); When I con ...

The webpage must be designed to be compatible with screen resolutions starting from 800 x 600 pixels and higher, utilizing Angular

I am working on developing a webpage that is specifically designed to work for resolutions of 800 x 600 pixels and higher. Any other resolutions will display the message "This website can only be accessed from desktops." Here is my approach using jQuery: ...

What is the best way to upload multiple files using ASP.Net and Jquery?

On my aspx page, I have included the following JavaScripts... <script src="jquery-1.3.2.js" type="text/javascript"></script> <script src="jquery.MultiFile.js" type="text/javascript"></script> In addition, I have inserted the follo ...

Query Selector(jQuery selector) is a powerful tool for

Here is the HTML Table structure: <table class="display" style="width: 1000px;" id="failoverServers"> <thead> <tr> <th class="row_selector_head"> <input type='checkbox' class='select_all_ch ...

span element causing border-spacing problem

Is there a way to adjust the spacing between these borders? I've tried using border-spacing but it doesn't seem to be working. https://i.sstatic.net/ZY05g.png {{#each spacing}} <span class='space'> {{business}} ({{Count}}) < ...

Arrangement of div elements tailored to fit the size of the viewport

I am working on creating a grid of divs that will cover the entire viewport. To start, I want to have a grid that is 7 divs wide and 10 divs high. Below is the code snippet I've written so far to set the size of the div elements: function adjustHeig ...