skip to Main Content

I’ve looked at lots of examples but cannot get this to work. At best, I end up with a version of the existing array with properties replicated that should be lost in the summary.

I would like to output a new array of totals for each location and not include any details for specific periods, the period property etc.
I think my issue is with Object.assign({}, o); where I am creating a full copy, but I can’t see how to just create an object with just the location, to which the totals can be added.

This is a simplified example and in the original I am summing multiple columns and dropping multiple columns.

let helper = {};
let locationPeriodCounts = [
  {"period": "2023-10-21", "location": "228", "countIn": 6},
  {"period": "2023-10-22", "location": "228", "countIn": 8},
  {"period": "2023-10-23", "location": "228", "countIn": 3},
  {"period": "2023-10-24", "location": "228", "countIn": 1},
  {"period": "2023-10-21", "location": "229", "countIn": 5},
  {"period": "2023-10-22", "location": "229", "countIn": 18},
  {"period": "2023-10-23", "location": "229", "countIn": 8},
  {"period": "2023-10-24", "location": "230", "countIn": 3},
  {"period": "2023-10-25", "location": "230", "countIn": 4}
];

let locationCounts = locationPeriodCounts.reduce(function(r, o) {
  let key = o.location;
  if (!helper[key]) {
    helper[key] = Object.assign({}, o); // create a copy of o
    helper[key].totalCount = 0;
    r.push(helper[key]);
  } else {
    helper[key].totalCount += o.countIn;
  }
  return r;
}, []);

console.log(locationCounts);

This is what I’m looking for as output…

[
  {"location": "228", "totalCount": 18},
  {"location": "229", "totalCount": 31},
  {"location": "230", "totalCount": 7}
];

2

Answers


  1. I added an Object.entries to convert to object array

    let locationCounts = Object.entries(
      locationPeriodCounts
      .reduce(function(acc, {location,countIn}) {
        acc[location] ??= 0; // create if it does not exist
        acc[location] += countIn; // always add to the total
        return acc;
      }, {})
    ).map(([location, totalCount]) => ({location,  totalCount }));
    
    console.log(locationCounts)
    <script>
        let locationPeriodCounts = [
          {"period": "2023-10-21", "location": "228", "countIn": 6},
          {"period": "2023-10-22", "location": "228", "countIn": 8},
          {"period": "2023-10-23", "location": "228", "countIn": 3},
          {"period": "2023-10-24", "location": "228", "countIn": 1},
          {"period": "2023-10-21", "location": "229", "countIn": 5},
          {"period": "2023-10-22", "location": "229", "countIn": 18},
          {"period": "2023-10-23", "location": "229", "countIn": 8},
          {"period": "2023-10-24", "location": "230", "countIn": 3},
          {"period": "2023-10-25", "location": "230", "countIn": 4}
        ];
    
    </script>
    Login or Signup to reply.
  2. I found @mplungjan‘s response much more smart and compact than mine.
    This, however, is what I usually do:

    let locationPeriodCounts = [
        { "period": "2023-10-21", "location": "228", "countIn": 6 },
        { "period": "2023-10-22", "location": "228", "countIn": 8 },
        { "period": "2023-10-23", "location": "228", "countIn": 3 },
        { "period": "2023-10-24", "location": "228", "countIn": 1 },
        { "period": "2023-10-21", "location": "229", "countIn": 5 },
        { "period": "2023-10-22", "location": "229", "countIn": 18 },
        { "period": "2023-10-23", "location": "229", "countIn": 8 },
        { "period": "2023-10-24", "location": "230", "countIn": 3 },
        { "period": "2023-10-25", "location": "230", "countIn": 4 }
    ]
    
    let locationCounts = locationPeriodCounts.reduce((acc, { location, countIn }) => {
    
        let currLocationCount = acc.find(count => count.location === location)
    
        if (currLocationCount) {
            currLocationCount.totalCount += countIn
        } else {
            acc.push({
                location: location,
                totalCount: countIn
            })
        }
    
        return acc;
    }, []);
    
    //If you also need sorting
    locationCounts.sort((a, b) => {
        //return a.totalCount - b.totalCount // asc
        return b.totalCount - a.totalCount //desc
    })
    
    console.log(locationCounts);
    

    And this is the output:

    [
       {location: "229", totalCount: 31},
       {location: "228", totalCount: 18},
       {location: "230", totalCount: 7}
    ]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search