Home > Enterprise >  Best way to group an array with property of object and how to render the result
Best way to group an array with property of object and how to render the result

Time:12-08

I tried to find a solution to my problem but couldn't find one, so I have an array of objects (products), each product has a category property and I want to group the products by categories. I managed to do that using reduce() but now I would need to render the category name first and then the products in that category.

Example:

const products = [
 {id: 1, category: 'Burgers', name: 'Burger'},
 {id: 2, category: 'Burgers', name: 'Cheeseburger'},
 {id: 3, category: 'Meals', name: 'Burger meal'},
 {id: 4, category: 'Meals', name: 'Cheeseburger meal'}
]

I need to group these products by category and I did that with reduce()

const menu = products.reduce((menu, product) => {
    if (menu[product.category] == null) menu[product.category] = []
    menu[product.category].push(product)
    return menu
}, [])

So now my result is

[Burgers: Array(2), Meals: Array(2)]

But I would want to render those with map() so how can I do that? Or how can I change the result? I would want the result to be like

Categories: [
 {
   0: 
   name: 'Burgers',
   products: Array(2)
 },
 {
   1:
   name: 'Meals',
   products: Array(2)
 }
]

That way I could render that array with map like

<div>
  {menu.map((c, index) =>
    <Category key={index} name={c.name} products={c.products} />
  )}
</div>

CodePudding user response:

const products = [
 {id: 1, category: 'Burgers', name: 'Burger'},
 {id: 2, category: 'Burgers', name: 'Cheeseburger'},
 {id: 3, category: 'Meals', name: 'Burger meal'},
 {id: 4, category: 'Meals', name: 'Cheeseburger meal'}
]

const menu = products.reduce((acc, product)=> {
    const categoryIndex = acc.findIndex(item => item.name == product.category);
    if(categoryIndex > -1){
        acc[categoryIndex].products.push(product);
    }else {
        acc.push({ name: product.category, products: [product] })
    };
    return acc;
}, []);

console.log(menu)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

At first, I was only answering the pure javascript question about how to groupby

products.reduce((prev, curr) => {
  if(!prev.categories.hasOwnProperty(curr.category)) prev.categories[curr.category] = prev.count  

  const index = prev.categories[curr.category]
  if(!Array.isArray(prev.menu[index])) prev.menu[index] = []

  prev.menu[index].push(curr) 

  return prev
}, {count: 0, menu: [], categories:{}}).menu

From there, I guess your map would look like this:

<div>
  {menu.forEach((c, i) =>  
     <Category key={i} name={c[0].category} products={c} />
  )}
</div>
  • Related