Categorize objects in an array based on their groups

How can I categorize this array of objects by their categoria?

items = [
  { categoria: 'Sandwiches', nombre: 'Sandwich de Pollo',  precio: 12 },
  { categoria: 'Sandwiches', nombre: 'Sandwich de Lomo',  precio: 12 },
  { categoria: 'Helados', nombre: 'Helado de 1 bola', precio: 5 },
  { categoria: 'Helados', nombre: 'Helado de 2 bolas', precio: 8 },
  { categoria: 'Helados', nombre: 'Helado de 3 bolas', precio: 10 },
];

This is the desired result, implemented in Typescript with Angular:

itemsResult = [
{
  categoria: 'Sandwiches',
  items: [
    { nombre: 'Sandwich de Pollo',  precio: 12 },
    { nombre: 'Sandwich de Lomo',  precio: 12 },
  ]
},
{
  categoria: 'Helados',
  items: [
    { nombre: 'Helado de 1 bola', precio: 5 },
    { nombre: 'Helado de 2 bolas', precio: 8 },
    { nombre: 'Helado de 3 bolas', precio: 10 },
  ]
 },
];

I attempted using a reduce, but it returned an object instead of an array.

this.itemsGroup = this.items.reduce((r, a) => {
      r[a.categoria] = r[a.categoria] || [];
      r[a.categoria].push(a);
      return r;
    }, Object.create(null));
    console.log(this.itemsGroup);

{
  Sandwiches: [
   { nombre: 'Sandwich de Pollo',  precio: 12 },
   { nombre: 'Sandwich de Pollo',  precio: 15 }
  ],
  Helados: [
   { nombre: 'Helado de 1 bola', precio: 5 },
   { nombre: 'Helado de 2 bolas', precio: 8 },
   { nombre: 'Helado de 3 bolas', precio: 10 }
  ]
}

Answer №1

If you're looking to group items based on a specific property, you can achieve this using the _.groupBy() function from underscore.js.

const items = [
  { categoria: 'Sandwiches', nombre: 'Sandwich de Pollo', precio: 12 },
  { categoria: 'Sandwiches', nombre: 'Sandwich de Lomo', precio: 12 },
  { categoria: 'Helados', nombre: 'Helado de 1 bola', precio: 5 },
  { categoria: 'Helados', nombre: 'Helado de 2 bolas', precio: 8 },
  { categoria: 'Helados', nombre: 'Helado de 3 bolas', precio: 10 },
];

let newArr = [];
let grp = _.groupBy(items, "categoria");

for (const obj in grp) {
  newArr.push({ categoria: obj, items: grp[obj] });
}

console.log(newArr, 'newArr');

If you prefer not to use underscore.js, you can achieve the same result using the reduce() method!

const items = [
  { categoria: 'Sandwiches', nombre: 'Sandwich de Pollo', precio: 12 },
  { categoria: 'Sandwiches', nombre: 'Sandwich de Lomo', precio: 12 },
  { categoria: 'Helados', nombre: 'Helado de 1 bola', precio: 5 },
  { categoria: 'Helados', nombre: 'Helado de 2 bolas', precio: 8 },
  { categoria: 'Helados', nombre: 'Helado de 3 bolas', precio: 10 },
];
let newArr = [];

let grp = items.reduce((group, product) => {
  const { categoria } = product;
  group[categoria] = group[categoria] ?? [];
  group[categoria].push(product);
  return group;
}, {});

for (const obj in grp) {
  newArr.push({ categoria: obj, items: grp[obj] });
}

console.log(newArr, 'newArr');

Answer №2

Here is my approach:

const items = [
  { category: "Sandwiches", name: "Chicken Sandwich", price: 12 },
  { category: "Sandwiches", name: "Steak Sandwich", price: 12 },
  { category: "Ice Creams", name: "1 Scoop Ice Cream", price: 5 },
  { category: "Ice Creams", name: "2 Scoop Ice Cream", price: 8 },
  { category: "Ice Creams", name: "3 Scoop Ice Cream", price: 10 }
];

const groupedItems = items.reduce((prev, { category, ...item }) => {
  const id = prev.findIndex((group) => group.category === category);
  id >= 0 
    ? prev[id].items.push(item)
    : prev.push({category, items: [item]})
  return prev
}, []);

console.log(groupedItems);

In my opinion, this solution is more concise and easier to understand compared to @MayurVaghasiya's solution.

Furthermore, it does not rely on any external dependencies.

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

Stop the CSS animation on the circular menu to toggle it open and closed

I have a circular menu with the added code "animation: pulse infinite". The menu can be opened and dragged around. Now, I want to add a pause animation so that it stops for a while when the menu is opened and closed. I tried adding "animation-play-state" ...

Omit a specific route from a middleware

I've implemented middleware to check user session on all routes. It simply redirects if the user is not logged in, otherwise it continues to the next function. router.use(function(req, res, next){ if(!req.user){ res.redirect('/login& ...

The Truffle test encounters an issue: "Error: Trying to execute a transaction that calls a contract function, but the recipient address ___ is not a contract address."

Every time I run truffle test in the terminal, I encounter the following error message: Error: Attempting to run a transaction which calls a contract function, but the recipient address 0x3ad2c00512808bd7fafa6dce844a583621f3df87 is not a contract address. ...

Using inline JavaScript to display the current year in text format

I want to make the year in my copyright statement dynamic, so that it automatically updates. Could I use JavaScript to insert the current year after the dash? Here's an example of what I'm looking for: 1994-2015 1994- ...

Obtaining your CSGO inventory via Steam API using jsonp: A step-by-step guide

Hey there! I'm currently facing an issue while trying to access a player's CSGO inventory using Valve's API. Unfortunately, I keep running into the error message stating that no 'access-control-allow-origin' header is present on th ...

Using the "let" keyword in JavaScript can create closures

function first(){ var items = document.getElementsByTagName("li"); for(var x = 0; x < items.length; x++){ items[x].onclick = function() { console.log(x); } } } function second(){ var items = document.getElem ...

<select> dropdown menu for selecting specific files opened by JavaScript

Currently, I am converting CSV files into JSON format and then manipulating them to generate arrays that will be used by jQuery to create a graph. My goal is to implement a dropdown menu that allows the user to choose a specific CSV file for graph creatio ...

Enhance a React component by including additional properties when passing it into another component through props

I have a parent element with a dynamically changing height that I need to pass down to its child elements. To get and set the height of the parent element, I am utilizing a ref. The challenge lies in passing this height value from the parent component to ...

Guide on extracting data from an API request in JavaScript and passing it to a React component

I am facing an issue with retrieving the value of an API call in JavaScript for my React component. I have a JavaScript file that successfully calls an API and returns results. However, when I attempt to use the JavaScript function within the useEffect hoo ...

Tips for enabling Regex patterns to include spaces

var validate = /^[@#&%][a-zA-Z0-9\s]{4}$/; I want to modify this Regex so that it allows spaces as well. ...

I'm curious as to why styled components weren't working before

I'm attempting to utilize the before on styled components in React, but it doesn't seem to be functioning correctly. Prior to adding before, the background image was displayed, but after its inclusion, the image is no longer showing up; import st ...

Extracting the toArray value from the sortable() function

It feels like I must be making a simple mistake here, as this seems like such a basic issue. The problem I'm facing involves using the sortable() function on a short list and wanting to retrieve an array of the sorted list's IDs. While my code a ...

To ensure proper formatting, I must include a comma operator for numbers while typing and limit the decimal places to two

Could someone assist me in formatting a number to include commas and restrict the decimal places to two using regex? I have attempted the following, but need help making it work properly. Currently, when I enter a number it shows up as 1231244, however I ...

Exploring the power of global injectors in Angular 7 for component inheritance

Recently, I have been following a method outlined in a blog post on MSDN to simplify the extension of components without having to include all dependencies in the super() call. However, this approach seems to have ceased working in Angular 7 with Typescrip ...

Issues arise when attempting to use $http.get in AngularJs and Ionic

I've been working on loading data from a MySQL database using a PHP file and then displaying the results in my AngularJS file. Unfortunately, I'm encountering some issues with this process. I attempted to use the $http service along with the .get ...

Upon refreshing the page in Javascript, the element mysteriously vanishes without a trace

After implementing a function that should display "barProgress25" and hide "barProgress0" when a button is clicked, I encountered an issue. Upon clicking the button, the function works as intended but upon page refresh, "barProgres ...

What is the correct way to incorporate Regular Expressions in Selenium IDE coding?

Using regular expressions to check for a correct answer from a prompt has been challenging. The current expression seems to be giving unexpected results, marking valid answers as false. For instance, when inputting the number 3, Selenium indicates that the ...

Guide to Chrome's Document Object Model and JavaScript Reference

Does Chrome have a Javascript/DOM Reference page similar to the Mozilla Developer Network? I am curious about other websites that provide detailed information on Chrome's specific interpretations of web standards. ...

Issues with Bootstrap Navigation Javascript Functionality

I'm having trouble with my JavaScript code that is supposed to open the second layer of my navigation. I can't figure out why it's not working. Am I missing something obvious? It's a bit warm in my office right now. ...

What makes the addClass and removeClass functions in jQuery work correctly only when used with the alert function?

Attempting to create my own slider using jQuery, here's a working example: $(document).ready(function(){ $(".carousel-indicators li").click(function(){ $(".carousel-indicators li").css("background-color", "transparent"); $(this).css("background-c ...