Search code examples
javascriptecmascript-6ecmascript-5

Combine objects of an array's subcategories based on its category


Q: Here is an array of multiple objects (category and sub categories).

let cats = [
  { cat: 'letter', subCat: 'A'}, 
  { cat: 'letter', subCat: 'B'}, 
  { cat: 'number', subCat: '2'}, 
  { cat: 'number', subCat: '3'}, 
  { cat: 'number', subCat: '4'}, 
  { cat: 'other', subCat: '+'}, 
]

need to convert this cats object like this -

cats = [
    { cat: 'letter', subCat: ['A', 'B'] },
    { cat: 'number', subCat: ['2', '3', '4'] },
    { cat: 'other', subCat: ['+'] }
  ]

Solution

  • You can achieve this using a simple reduce

    let cats=[{cat:'letter',subCat:'A'},{cat:'letter',subCat:'B'},{cat:'number',subCat:'2'},{cat:'number',subCat:'3'},{cat:'number',subCat:'4'},{cat:'other',subCat:'+'},]
    
    const merged = cats.reduce((a, {cat, subCat})=>{
      a[cat] = a[cat] || {cat, subCat:[]}
      a[cat]["subCat"].push(subCat)
      return a;
    },{})
    
    console.log(Object.values(merged))

    Create an accumulator with each unique cat as key and the object you need in the final array as value like this:

    {
      "letter": {
        "cat": "letter",
        "subCat": [
          "A",
          "B"
        ]
      }
    }
    

    Then use Object.values to get only the values in an array.

    You could do the whole thing in one go:

    let cats = [{cat:'letter',subCat:'A'},{cat:'letter',subCat:'B'},{cat:'number',subCat:'2'},{cat:'number',subCat:'3'},{cat:'number',subCat:'4'},{cat:'other',subCat:'+'},]
    
    const merged = Object.values(cats.reduce((a,{cat, subCat}) => (
      (a[cat] = a[cat] || {cat, subCat:[]})["subCat"].push(subCat), a
    ),{}))
    
    console.log(merged)