• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

85
Views
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 3 years ago · Juan Pablo Isaza
2 answers
Answer question

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 3 years ago · Juan Pablo Isaza Report

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 3 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error