Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

126
Visualizações
get total price from array of objects per specific user using .reduce in javascript

I have this array of objects

const items = [
  {
    id: '121',
    itemDate: '2022-04-28',
    itemName: 'testname1',
    itemCategory: 'Category A',
    itemPrice: { price: '100', currency: 'GBP' },
    createdBy: {
      username: 'user1',
      name: 'Name 1',
      date: '2022-04-28T22:41:59',
    },
  },
  {
    id: '122',
    itemDate: '2022-04-28',
    itemName: 'testname2',
    itemCategory: 'Category B',
    itemPrice: { price: '100', currency: 'GBP' },
    createdBy: {
      username: 'user2',
      name: 'Name 2',
      date: '2022-04-28T22:42:44',
    },
  },
  {
    id: '122',
    itemDate: '2022-04-28',
    itemName: 'testname3',
    itemCategory: 'Category C',
    itemPrice: { price: '200', currency: 'GBP' },
    createdBy: {
      username: 'user2',
      name: 'Name 2',
      date: '2022-04-28T22:43:16',
    },
  },
]

Code I'm using:

items.reduce(function (c, x) {
  if (!c[x.createdBy.username])
    c[x.createdBy.username] = {
      username: x.createdBy.username,
      total: 0,
    }
  c[x.createdBy.username].total += Number(x.itemPrice.price)
  return c
}, [])

This part gives me the following output:

items :>>  [
  user1: { username: 'user1', total: 100},
  user2: { username: 'user2', total: 300}
]

So I tried this to get rid of the object names:

let output = []
let totalSum = 0

for (const username in items) {
  let temp = {
    username: items[username].username,
    total: items[username].total,
  }
  totalSum = totalSum + items[username].total
  output.push(temp)
}
output.push({ username: 'allUsers', total: totalSum })

return output

And final output is as I want it now:

output :>>  [
  { username: 'user1', total: 100 },
  { username: 'user2', total: 300 },
  { username: 'allUsers', total: 400}
]

My two questions...

Is there a way to update the .reduce part so that I'd get an object without the name at the beggining, without having to use the for loop?

Is there also a way to implement the part that would sum up all the totals?

Thank you

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

Code Sample (without comments/description)

const groupAndAdd = arr => (
  Object.values(
    arr.reduce(
      (acc, {createdBy : {username}, itemPrice: {price}}) => {
        acc.allUsers ??= { username: 'allUsers', total: 0};
        acc.allUsers.total += +price;
        if (username in acc) {
          acc[username].total += +price;
        } else {
          acc[username] = {username, total: +price};
        }
        return acc;
      },
      {}
    )
  )
);

Presented below is a working demo to achieve the desired objective, with notes/comments to help understand.

Code Snippet

// method to group by user and sum prices
const groupAndAdd = arr => (
  // extract the values from the intermediate result-object
  Object.values(
    arr.reduce(             // generate result as object
      (acc, {createdBy : {username}, itemPrice: {price}}) => {
        // above line uses de-structuring to directly access username, price
        // below uses logical nullish assignment to set-up "allUsers"
        acc.allUsers ??= { username: 'allUsers', total: 0};
        
        // accumulate the "price" to the all-users "total"
        acc.allUsers.total += +price;
        
        // if "acc" (accumulator) has "username", simply add price to total
        if (username in acc) {
          acc[username].total += +price;
        } else {
          // create an object for the "username" with initial total as "price"
          acc[username] = {username, total: +price};
        }
        
        // always return the "acc" accumulator for ".reduce()"
        return acc;
      },
      {}                // initially set the "acc" to empty object
    )
  )          // if required, use ".sort()" to move the all-users to last position in array
);

const items = [{
    id: '121',
    itemDate: '2022-04-28',
    itemName: 'testname1',
    itemCategory: 'Category A',
    itemPrice: {
      price: '100',
      currency: 'GBP'
    },
    createdBy: {
      username: 'user1',
      name: 'Name 1',
      date: '2022-04-28T22:41:59',
    },
  },
  {
    id: '122',
    itemDate: '2022-04-28',
    itemName: 'testname2',
    itemCategory: 'Category B',
    itemPrice: {
      price: '100',
      currency: 'GBP'
    },
    createdBy: {
      username: 'user2',
      name: 'Name 2',
      date: '2022-04-28T22:42:44',
    },
  },
  {
    id: '122',
    itemDate: '2022-04-28',
    itemName: 'testname3',
    itemCategory: 'Category C',
    itemPrice: {
      price: '200',
      currency: 'GBP'
    },
    createdBy: {
      username: 'user2',
      name: 'Name 2',
      date: '2022-04-28T22:43:16',
    },
  },
];

console.log('group and add prices per user: ', groupAndAdd(items));
.as-console-wrapper { max-height: 100% !important; top: 0 }

Explanation

Inline comments added to the snippet above.

PS: If you'd like to add value to stackoverflow community,

Please consider reading: What to do when my question is answered Thank you !

about 4 years ago · Juan Pablo Isaza Relatório

0

For your first question, you're initialising correctly as an array, but you're using just object. Two ways you can do this.

First Option

let something = items.reduce(function(c, x) {
  if (!c[x.createdBy.username])
    c[x.createdBy.username] = {
      username: x.createdBy.username,
      total: 0,
    }
  c[x.createdBy.username].total += Number(x.itemPrice.price)
  return c
}, {});
something = Object.values(something);

Second Option

I was thinking of using just push, but seems it's not possible, so the above is the only option.

Using push is possible, but it'll get too complicated by checking with find and updating the correct array element.


For your second question of summing up all the totals, you can use the simple syntax of:

const sum = arr.reduce((a, c) => a + c, 0);

This is the minimum code you need for array of numbers to be summed.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda