javascriptarray-reduce

How to get the wanted result using reduce javascript?


I'm trying to understand how the reduce method work. The groupBy function only return object that is grouped by category. How do I get the wanted result below? I have tried many ways but none works.

const PRODUCTS = [
  { category: "Fruits", price: "$1", stocked: true, name: "Apple" },
  { category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
  { category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
  { category: "Vegetables", price: "$2", stocked: true, name: "Spinach" },
  { category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin" },
  { category: "Vegetables", price: "$1", stocked: true, name: "Peas" },
];

function groupBy(objectArray, property) {
  return objectArray.reduce((previousResult, currentValue) => {
    const key = currentValue[property];
    const curGroup = previousResult[key] ?? [];

    return { ...previousResult, [key]: [...curGroup, currentValue] };
  }, {});
}

console.log(groupBy(PRODUCTS, "category"));
.as-console-wrapper { max-height: 100% !important; }

const wantedResult = [
  {
    category: "Fruits",
    item: [
      { category: "Fruits", price: "$1", stocked: true, name: "Apple" },
      { category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
      { category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
    ],
  },
  {
    category: "Fruits",
    item: [
      { category: "Fruits", price: "$1", stocked: true, name: "Apple" },
      { category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
      { category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
    ],
  },
];

Solution

  • Assuming you want a result including vegetables and not just fruits duplicated, extract the entries from the grouped object and map them to the new format

    // Just your code minified
    const PRODUCTS=[{category:"Fruits",price:"$1",stocked:!0,name:"Apple"},{category:"Fruits",price:"$1",stocked:!0,name:"Dragonfruit"},{category:"Fruits",price:"$2",stocked:!1,name:"Passionfruit"},{category:"Vegetables",price:"$2",stocked:!0,name:"Spinach"},{category:"Vegetables",price:"$4",stocked:!1,name:"Pumpkin"},{category:"Vegetables",price:"$1",stocked:!0,name:"Peas"},];function groupBy(e,t){return e.reduce((e,r)=>{let c=r[t],a=e[c]??[];return{...e,[c]:[...a,r]}},{})}
    
    const wantedResult = Object.entries(groupBy(PRODUCTS, "category")).map(
      // Map each "category" key and "item" array value pair
      // to an object with "category" and "item" properties
      ([category, item]) => ({ category, item })
    );
    
    
    console.log(wantedResult);
    .as-console-wrapper { max-height: 100% !important; }