AndyJamesN
AndyJamesN

Reputation: 498

Combine objects in array of objects with same values

Here is an array of objects with categories and the solution each category belongs to. Solutions are repeated but categories are unique.

const categories = [
  { category: 'Patch Leads', solution: 'Data Solutions' },
  { category: 'Cables', solution: 'Data Solutions' },

  { category: 'Nails', solution: 'Hardware' },
  { category: 'Locks', solution: 'Hardware' },
  { category: 'Screws', solution: 'Hardware' },

  { category: 'Cabinets', solution: 'Cabinet Solutions' },
  { category: 'Swing Frames', solution: 'Cabinet Solutions' },
  { category: 'Racks', solution: 'Cabinet Solutions' },

  { category: 'Fire Cables', solution: 'Fire Solutions' },

];

I need to return a new solutions array of solution objects. This is the format of the final result. All of the data to get this format is available when looping like index for the id's but I just can't get the format of my code right.

const solutions = [
  {
    id: "0",
    name: "Data Solutions",
    categories: [
      {
        id: "0",
        name: "Cables",
        slug: "cables"
      },
      {
        id: "1",
        name: "Patch Leads",
        slug: "patch-leads"
      }
    ]
  },
  {
    id: "1",
    name: "Hardware",
    categories: [
      {
        id: "0",
        name: "Nails",
        slug: "nails"
      },
      {
        id: "1",
        name: "Locks",
        slug: "locks"
      },
      {
        id: "2",
        name: "Screws",
        slug: "screws"
      }
    ]
  },
  {
    id: "2",
    name: "Cabinet Solutions",
    categories: [
      {
        id: "0",
        name: "Cabinets",
        slug: "cabinets"
      },
      {
        id: "1",
        name: "Swing Frames",
        slug: "swing-frames"
      },
      {
        id: "2",
        name: "Racks",
        slug: "racks"
      }
    ]
  },
  {
    id: "3",
    name: "Fire Solutions",
    categories: [
      {
        id: "0",
        name: "Fire Cables",
        slug: "gire-cables"
      }
    ]
  }
]

Upvotes: 1

Views: 374

Answers (3)

Amir Makram
Amir Makram

Reputation: 12988

You can use some classes to make to recreate objects faster.

const categories = [
    { category: 'Patch Leads', solution: 'Data Solutions' },
    { category: 'Cables', solution: 'Data Solutions' },

    { category: 'Nails', solution: 'Hardware' },
    { category: 'Locks', solution: 'Hardware' },
    { category: 'Screws', solution: 'Hardware' },

    { category: 'Cabinets', solution: 'Cabinet Solutions' },
    { category: 'Swing Frames', solution: 'Cabinet Solutions' },
    { category: 'Racks', solution: 'Cabinet Solutions' },

    { category: 'Fire Cables', solution: 'Fire Solutions' },
];

class category{
    constructor(id,name){
        this.id = id;
        this.name = name;
        this.slug = name;
    }
}
class NewOne {
    constructor(id,name,categories=[]) {
        this.id = id;
        this.name = name;
        this.categories = categories;
    }
}
let solutions = [];

solutions.push(new NewOne(0, categories[0].solution,[new category(0,categories[0].category)]));

let newArrayIndex = 0;
let idPlusOne = 1;

for(index in categories){
    if(solutions[newArrayIndex].name !== categories[index].solution){
        solutions.push(new NewOne(index, categories[index].solution,[new category(0,categories[index].category)]));
        newArrayIndex++;
        idPlusOne=1;
    }else{
        solutions[newArrayIndex].categories.push(new category(idPlusOne,categories[index].category));
        idPlusOne++;
    }
}

Upvotes: 0

Nikhil
Nikhil

Reputation: 6643

You can use reduce() method to do that. While iterating, if current item already exists then append current category to existing item. If not, create a new item with current category.

const categories = [ { category: 'Patch Leads', solution: 'Data Solutions' }, { category: 'Cables', solution: 'Data Solutions' }, { category: 'Nails', solution: 'Hardware' }, { category: 'Locks', solution: 'Hardware' }, { category: 'Screws', solution: 'Hardware' }, { category: 'Cabinets', solution: 'Cabinet Solutions' }, { category: 'Swing Frames', solution: 'Cabinet Solutions' }, { category: 'Racks', solution: 'Cabinet Solutions' }, { category: 'Fire Cables', solution: 'Fire Solutions' }, ];

var solutions = categories.reduce((acc, curr) => {
  let item = acc.find(item => item.name === curr.solution);

  if (item) {
    item.categories.push({
      "id": item.categories.length,
      "name": curr.category,
      "slug": curr.category.toLowerCase().replace(' ', '-')
    });
  } else {
    acc.push({
      "id": acc.length,
      "name": curr.solution,
      "categories": [{
        "id": 0,
        "name": curr.category,
        "slug": curr.category.toLowerCase().replace(' ', '-')
      }]
    });
  }

  return acc;
}, []);

console.log(solutions);

Upvotes: 3

Dhananjai Pai
Dhananjai Pai

Reputation: 6015

The below code creates an intermediate array map of solutions to category and then uses it to generate output of the required format by using the keys and values of the mapped Object.

const categories = [
  { category: 'Patch Leads', solution: 'Data Solutions' },
  { category: 'Cables', solution: 'Data Solutions' },

  { category: 'Nails', solution: 'Hardware' },
  { category: 'Locks', solution: 'Hardware' },
  { category: 'Screws', solution: 'Hardware' },

  { category: 'Cabinets', solution: 'Cabinet Solutions' },
  { category: 'Swing Frames', solution: 'Cabinet Solutions' },
  { category: 'Racks', solution: 'Cabinet Solutions' },

  { category: 'Fire Cables', solution: 'Fire Solutions' },

];

const solutionMap = categories.reduce((acc,item) => {
 if(!acc[item.solution]) 
   acc[item.solution] = [];
 acc[item.solution].push(item.category); 
 return acc;
},{});

const solutions = Object.entries(solutionMap).map(([key,val],id) => ({
  id,
  name: key,
  categories: val.map((category,idx) => ({id: idx, name: category, slug: category.toLowerCase().replace(' ','-')}))
}));

console.log(solutions);

Upvotes: 0

Related Questions