Combine an array of objects and their properties. Remove object after combining

后端 未结 4 1762
梦如初夏
梦如初夏 2021-01-29 08:18

I need to merge the objects together. The resource property is what determines if the objects can be merged. To determine where the hours property valu

4条回答
  •  灰色年华
    2021-01-29 08:28

    One technique is to loop over each member, find the first one with that resource, update the totals in it, and then filter so as to retain only the first occurrences.

    members.filter(member => {
      const first = members.find(m => m.resource === member.resource);
    
      if (member.billable) first.totalBillableHours += member.hours;
      else first.totalNonBillableHours += member.hours;
      first.totalHours += member.hours.
    
      return first === member;
    });
    

    A more orthodox approach would be to group the objects by resource, creating an array of objects for each resource, and then transform that into your desired output, as in

    totals(groupBy(members, 'resource'))
    

    groupBy would be defined as producing something of the form:

    {
      resource1: [obj, obj],
      resource2: [obj, obj]
    }
    

    To take totals first, that would be

    function totals(groups) {
      const hours    = m => m.hours;
      const billable = m => m.billable;
      const not      = f => x => !f(x);
    
      return Object.keys(groups).map(resource => {
        const members          = groups[resource];
        const totalHours       = sum(members.map(hours));
        const billableHours    = sum(members.filter(billable).map(hours));
        const nonBillableHours = sum(members.filter(not(billable)).map(hours));
    
        return {resource, totalHours, billableHours, nonBillableHours};
      });
    }
    

    sum can be written as

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

    There are many implementations of groupBy out there, including ones provided by libraries such as underscore. Here's a real simple version:

    function groupBy(arr, prop) {
      return arr.reduce((result, obj) {
        const key = obj[prop];
        if (!result[key]) result[key] = [];
        result[key].push(obj);
        return result;
      }, {});
    }
    

提交回复
热议问题