How to group a list in javascript and calculate subtotals?

Asked

Viewed 225 times

5

I have the following list:

nomes = [
  { nome: "flavio", valor: 10 },
  { nome: "flavio", valor: 20 },
  { nome: "fran", valor: 30 },
  { nome: "fran", valor: 40 },
  { nome: "Roberto", valor: 50},
  { nome: "Roberto", valor: 50 }
];

How do I get:

subtotais = [
  {nome:"flavio", total:30},
  {nome:"fran", total:70},
  {nome:"Roberto", total:10}]

I appreciate any help.

  • Before arriving at this array, you have some query returns that data?

  • 1

    The value of Roberto is wrong in your example

  • I can’t find the green V to accept the answer.

  • Has any response helped solve the problem and can address similar questions from other users? If so, make sure to mark the answer as accepted. To do this just click on the left side of it (below the indicator of up and down votes).

2 answers

4

You can iterate the array to obtain the expected result:

function somar(antigo) {

  var resultado = [];

  antigo.reduce(function(novo, item) {
    if (!novo[item.nome]) {
      novo[item.nome] = {
        valor: 0,
        nome: item.nome
      };

      resultado.push(novo[item.nome]);
    }

    novo[item.nome].valor += item.valor;

    return novo;
  }, {});
  
  return resultado;
}

console.log(somar([
  { nome: "flavio", valor: 10 },
  { nome: "flavio", valor: 20 },
  { nome: "fran", valor: 30 },
  { nome: "fran", valor: 40 },
  { nome: "Roberto", valor: 50},
  { nome: "Roberto", valor: 50 }
]));

Translated of this OS response

Using ES6:

const somar = (itens) => {
  const total = itens.reduce((acumulador, { nome, valor }) => {
    acumulador[nome] = (acumulador[nome] || 0) + valor;
    return acumulador;
  }, {});

  return Object.keys(total).map((nome) => ({ nome, valor: total[nome] }));
};

// Teste da solução
const nomes = [
  { nome: 'flavio', valor: 10 },
  { nome: 'flavio', valor: 20 },
  { nome: 'fran', valor: 30 },
  { nome: 'fran', valor: 40 },
  { nome: 'Roberto', valor: 50},
  { nome: 'Roberto', valor: 50 }
];

console.log(JSON.stringify(somar(nomes)));

  • 1

    Wow. That’s fast. My first time here and I’m so grateful, Sorack.

  • OK. I could only check now. It worked perfectly. Thank you.

2

Another simple solution is to use a for normal to walk through each person, and realize if the person already exists in the array grouped through findIndex. If there is no add the new person, otherwise add the value.

Example:

pessoas = [
  { nome: "flavio", valor: 10 },
  { nome: "flavio", valor: 20 },
  { nome: "fran", valor: 30 },
  { nome: "fran", valor: 40 },
  { nome: "Roberto", valor: 50},
  { nome: "Roberto", valor: 50 }
];

let agrupados = [];
for (let pessoa of pessoas){
  let posicao = agrupados.findIndex(p => p.nome === pessoa.nome);
  if (posicao === -1){ //se não existe
    agrupados.push(pessoa); //adiciona
  }
  else { //se já existe
    agrupados[posicao].valor += pessoa.valor; //soma o valor
  }
}

console.log(agrupados);

  • Old way but works tb. Grateful. I would do so but wanted to use reduce(). I’m going to start building my library of code obtained here. Thank you very much.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.