0

So I have an existing array with three objects:

              [ { date: 3/12/2022, oService: 10}
                { date: 3/13/2022, oService: 12, aService: 1}
                { date: 3/13/2022, oService: 1 }]

Based on the date, I would like to get something that looks like the following:

                [ {date: 3/12/2022, oService: 10}
                  {date: 3/13/2022, oService: 13, aService: 1}]

additionally, I could have up to 10 services, so I cant reduce by prev.oService. I'll have an array of services that looks something like:

const Services = [aService, bService, cService, oService, yService]

  • What about Array.prototype.filter() (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)? – Alex Mar 15 '22 at 10:09
  • I tried that, but Im not sure how i would compare the previous dates with filter. – frederickpenn Mar 15 '22 at 10:14
  • I understand that you only want those entries in the array with a specific date? Then filter is the way to go. – Alex Mar 15 '22 at 10:17
  • So I want that if the entries share a date, and then they have matching services on those dates, to add those services values. – frederickpenn Mar 15 '22 at 10:20
  • 1
    Does this answer your question? [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – Dani Mar 15 '22 at 10:23
  • 1
    @Dani thats exactly what I have in the clipboard right now :) – Alex Mar 15 '22 at 10:28
  • its actually close, but still doesnt solve my question :/ – frederickpenn Mar 15 '22 at 11:32

1 Answers1

1

I think it's best to think of the problem as 2 different steps:

  • First, get all things that belong to the same date together. This is a groupBy that you should be able to look up on StackOverflow or borrow from an existing library.
  • Then, you merge each of the date groups in to a single object.

The merge operation is a bit more custom than the groupBy operation. You can implement it in many ways. I would propose to:

  • Implement merge to deal with just 2 objects
  • Inside merge, loop over all unique keys in those objects and sum them (excluding the date key)
  • To apply merge to a date group, use reduce. Note that it's safe to not provide a seed argument here, because you are guaranteed to not have empty groups.

// Merge two date-service entries in to one
const merge = (a, b) => {
  const merged = Object.assign({}, a);
  
  Object.keys(b).forEach(k => {
    if (k !== "date")
      merged[k] = (merged[k] || 0) + b[k];
  });
  
  return merged;
};

const input = [ { date: "3/12/2022", oService: 10},
                { date: "3/13/2022", oService: 12, aService: 1},
                { date: "3/13/2022", oService: 1 }];
          
// Create groups that have a matching date
const byDate = groupByProp("date", input);

// Reduce each group to a single item by merging
const all = Object.values(byDate).map(xs => xs.reduce(merge));

console.log(all);

// A basic `groupBy` implementation
function groupByProp(prop, xs) { 
  return xs.reduce(
    (groups, x) => {
      const k = x[prop];
      if (!groups[k]) groups[k] = [x];
      else groups[k].push(x);
      return groups;
    },
    {}
  );
}
user3297291
  • 22,592
  • 4
  • 29
  • 45