Ruan Duarte
Ruan Duarte

Reputation: 385

how to group array of objects by value in reactjs

Considering the array

const a1 = [
  { id: 1, nome: 'Ruan', status: { id: 1, posicao: 'goleiro' } },
  { id: 2, nome: 'Gleison', status: { id: 2, posicao: 'zagueiro' } },
  { id: 3, nome: 'Geraldo', status: { id: 2, posicao: 'zagueiro' } },
  { id: 4, nome: 'Heleno', status: { id: 3, posicao: 'atacante' } },
  { id: 5, nome: 'Djandel', status: { id: 3, posicao: 'atacante' } }
]

I've tried using reduce, but without success, I tried the code below

var groupBy = function(xs, key) {
  return xs.reduce(function(rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
  }, {});
  groupBy(a1, 'status')
};

I also tried with lodash

_.groupBy(a1, 'status');

I hope that 3 different arrays will return, one with the goleiros, another with the zagueiros and another with the atacantes

And how to display the information separately in the react view?

Upvotes: 2

Views: 5363

Answers (2)

jean182
jean182

Reputation: 3505

You can use group by like this:

_.groupBy(a1, "status.posicao")

To specify that you need to group them by status.posicao, take a look at this sandbox it will return an object with the three groups.

https://codesandbox.io/s/strange-sanne-icdy3?file=/src/index.js

Edit:

If you want to build your own function without lodash and assuming you know the shape of the object, you can build something like this (I'm using your array example):

const a1 = [
  { id: 1, nome: "Ruan", status: { id: 1, posicao: "goleiro" } },
  { id: 2, nome: "Gleison", status: { id: 2, posicao: "zagueiro" } },
  { id: 3, nome: "Geraldo", status: { id: 2, posicao: "zagueiro" } },
  { id: 4, nome: "Heleno", status: { id: 3, posicao: "atacante" } },
  { id: 5, nome: "Djandel", status: { id: 3, posicao: "atacante" } },
];

function groupBy(items) {
  return items.reduce((acc, curr) => {
    if (curr.status?.posicao) {
      const { posicao } = curr.status;
      const currentItems = acc[posicao];
  
      return { 
        ...acc,
        [posicao]: currentItems ? [...currentItems, curr] : [curr]
      };
    }
    return acc;
  }, {});
}

console.log(groupBy(a1))

Upvotes: 5

George Pandurov
George Pandurov

Reputation: 391

As @jean182 already told you what is the problem in your lodash example but didn't tell you how to fix your code I am adding this to answer that part of the question.

The problem in your reduce is that you are giving status as a key but status is an object and so instead of value you will be using it's memory address as a key so you will never have same keys here (rv[x[key]] = rv[x[key]] || []) and every time you will be falling back to the empty array. For your code to work you might change it to something like this:

var groupBy = function(xs, key) {
    return xs.reduce(function(rv, x) {
        const value = _.get(x, key)
        (rv[value] = rv[value] || []).push(x);
        return rv;
    }, {});
};
groupBy(a1, 'status.posicao')

Have in mind that here I am using lodash get as you have mentioned that you can use it, without it you would have to do more changes to your code to work.

Upvotes: 1

Related Questions