11

I have an array of object that have different values like

 items=[{id:1,category:"cat_1" , title:"My title 1"},{id:2,category:"cat_2" , title:"My title 2"},{id:6,category:"cat_1" , title:"Another title 1"},{id:1,category:"cat_3" , title:"My title 3"},{id:8,category:"cat_1" , title:"Third Title"},{id:2,category:"cat_2" , title:"Another title 2 "}]

I use array map to list the object and display them as

     {
     items.map((item) => (
        <h1>{item.category}</h1>
        <p>{item.title}</p>
    ))} 

My question is how do i iterate the item so as it groups the items by category as follows

cat_1
- My title 1
- Another title 1
- My title 3

cat_2
- My title 2
- Another title 2

cat_3
-Third Title

4 Answers 4

29

Use .reduce:

const items = [{
  id: 1,
  category: "cat_1",
  title: "My title 1"
}, {
  id: 2,
  category: "cat_2",
  title: "My title 2"
}, {
  id: 6,
  category: "cat_1",
  title: "Another title 1"
}, {
  id: 1,
  category: "cat_3",
  title: "My title 3"
}, {
  id: 8,
  category: "cat_1",
  title: "Third Title"
}, {
  id: 2,
  category: "cat_2",
  title: "Another title 2 "
}];
const cats = items.reduce((catsSoFar, { category, title }) => {
  if (!catsSoFar[category]) catsSoFar[category] = [];
  catsSoFar[category].push(title);
  return catsSoFar;
}, {});
console.log(cats);

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

6 Comments

@TerryLennox: That is an understatement! In fact, reduce is a general iteration operation, everything you can do with a FOREACH loop (for/in, for/of, Array.prototype.forEach), you can do with reduce! Once you have reduce, you no longer need map, filter, groupBy, sort, etc. (except for readability and clarity, of course). There is a simple sketch of a proof on the Wikipedia page for fold. So, reduce is not just "super powerful", it is in fact "all-powerful".
@JörgWMittag, but you could say the same thing about forEach and even plain for and map - the important part isn't using something that's sufficiently powerful ( qr.ae/RNMEGA ), but using something that's powerful enough and is semantically proper for what its effect is.
Well put @Jörg I'll check out the article!
@CertainPerformance: map is not general. It cannot change the length of the collection, for example, or return something that is not a collection. You cannot implement sum in terms of map, unless you abuse the fact that in ECMAScript, the mapping function can have side-effects and get access to the collection itself, thus mutating it.
@JörgWMittag My point was that you can use/abuse (for example) map to achieve something that's not maplike, just like you can use/abuse reduce to do something more suited to a method such as forEach filter etc.
|
5

I use lodash in a lot of projects as a general utility belt. If you decide to do something similar -- it would be simple as:

const data = [{
  id: 1,
  category: "cat_1",
  title: "My title 1"
}, {
  id: 2,
  category: "cat_2",
  title: "My title 2"
}, {
  id: 6,
  category: "cat_1",
  title: "Another title 1"
}, {
  id: 1,
  category: "cat_3",
  title: "My title 3"
}, {
  id: 8,
  category: "cat_1",
  title: "Third Title"
}, {
  id: 2,
  category: "cat_2",
  title: "Another title 2 "
}];

const groups = _.groupBy(data,  'category');

console.log(groups);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Comments

2

I would make CertainPerformance's answer a bit more concise:

    const items = [{
      id: 1,
      category: "cat_1",
      title: "My title 1"
    }, {
      id: 2,
      category: "cat_2",
      title: "My title 2"
    }, {
      id: 6,
      category: "cat_1",
      title: "Another title 1"
    }, {
      id: 1,
      category: "cat_3",
      title: "My title 3"
    }, {
      id: 8,
      category: "cat_1",
      title: "Third Title"
    }, {
      id: 2,
      category: "cat_2",
      title: "Another title 2 "
    }];
    const cats = items.reduce((catMemo, { category, title }) => {
      (catMemo[category] = catMemo[category] || []).push(title);
      return catMemo;
    }, {});
    console.log(cats);

1 Comment

how to render this in react
0

Readability is important, but for anyone who's looking for a one-liner:

const groupedItems = items.reduce((ob, item) => ({...ob, [item.category]: [...ob[item.category] ?? [], item]}), {})

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.