2

I have an object array like so:

 const data = [
    {category: {id: 1, name: 'beverage'}, title: 'Tea'},
    {category: {id: 1, name: 'beverage'}, title: 'Coffee'},
    {category: {id: 2, name: 'snacks'}, title: 'French fries'},
  ];

I want the result like so:

const transformed = [
  {
    category: "beverage",
    data: [{title:'coffee'},{title:'tea'}, ...]
  },
  {
    category: "snacks",
    data: [{title:'french fries'},...]
  },
..
]

What i did was:

 let transformed = data?.map(function (obj) {
    var result = {
      category: obj.category.title,
      data: [],
    };
    for (var key in obj) {
      if (obj.hasOwnProperty(key) && key === 'category') {
        result.values.push(obj);
      }
    }

    return result;
  });

But with this approach i am getting duplicate category names for every object in the array.

3
  • I'm confused on the expected result's second value being title where first is category... explanation on that or just something you missed? And if it's not an error, what differs from the two? Commented Nov 10, 2021 at 12:23
  • with ur code i get TypeError: Cannot read properties of undefined (reading 'push') Commented Nov 10, 2021 at 12:26
  • The new array should contain objects based on category names. For example the first object should contain the category name 'beverage' and then an array of beverage items in the list. It was mistakenly quoted as title instead of category Commented Nov 10, 2021 at 12:26

3 Answers 3

3

As with all grouping operations the key is to use reduce to build up a new object.

const data = [
    {category: {id: 1, name: 'beverage'}, title: 'Tea'},
    {category: {id: 1, name: 'beverage'}, title: 'Coffee'},
    {category: {id: 2, name: 'snacks'}, title: 'French fries'},
  ];
  
const result = Object.values(data.reduce( (a,i) => {
    a[i.category.id] = a[i.category.id] || {category:i.category.name, data:[]};
    a[i.category.id].data.push({title:i.title});
    return a;
},{}));

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

Clean! :) :thumbsup:
3

You could group by name of category and use an object for getting groupd values.

const 
    data = [{ category: { id: 1, name: 'beverage' }, title: 'Tea' }, { category: { id: 1, name: 'beverage' }, title: 'Coffee' }, { category: { id: 2, name: 'snacks' }, title: 'French fries' }],
    result = Object.values(data.reduce((r, { category: { name: category }, title  }) => {
        (r[category] ??= { category, data: [] }).data.push({ title });
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

3 Comments

Nice and clean! Pretty code.
Can you tell me the name of the pattern used to solve this problem? When we group objects by property and return the answer as Object.values(...)
it has no real name, but it's grouping with a hash table.
0

Check this out

const data = [
    {category: {id: 1, name: 'beverage'}, title: 'Tea'},
    {category: {id: 1, name: 'beverage'}, title: 'Coffee'},
    {category: {id: 2, name: 'snacks'}, title: 'French fries'},
  ];

const transform = (data) => {
  const grouped = data.reduce((acc, obj) => {
    const { category: { id, name }, title } = obj;
    acc[id] = (acc[id]) 
      ? { 
          ...acc[id], 
          data: [...acc[id].data, { title }], 
        }
      : { category: name, data: [{ title }] };

    return acc; 
  }, {});
  
  return Object.values(grouped);
};

console.dir(transform(data), {depth: null});
// [
//   { category: 'beverage', data: [{ title: 'Tea' }, { title: 'Coffee' }] },
//   { category: 'snacks', data: [{ title: 'French fries' }]}
// ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.