从对象数组中获取总和不同的项

时间:2018-09-26 15:37:14

标签: javascript arrays javascript-objects

我确实进行了搜索,找不到正确的答案。我有一个对象数组:

[ { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '505',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '404',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '303',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '203',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 950.4000000000001 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '202',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '500',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '400',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '300',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '201',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 864 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '200',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 } ]

我想要的是一个新的对象数组,这些对象显示currentMonth,employeeNumber,caLastName,caFirstName,rate_per_hour,clientType,totalHours之和和每个雇员的工资之和。因此,在此示例中,只有两个对象的数组。

我尝试了减少和过滤,但是我无法确切地知道我要去哪里。我宁愿不做循环,因为我怀疑这样会降低效率。

新数组看起来像:

[ { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 168,
    wages: 7286.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 168,
    wages: 6624 } ]

6 个答案:

答案 0 :(得分:4)

您可以利用减少和汇总数据之类的方式

const data = [ { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '505',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '404',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '303',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '203',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 950.4000000000001 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '202',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '500',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '400',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '300',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '201',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 864 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '200',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 } ]
    
const res = data.reduce((acc, obj) => {
     const index = acc.findIndex(item => item.employeeNumber === obj.employeeNumber);
     if(index > -1) {
         console.log(acc[index])
         acc[index] = {...acc[index], totalHours: acc[index].totalHours + obj.totalHours, wages: acc[index].wages + obj.wages};
     } else {
         acc = acc.concat([obj]);
     }
     return acc;
}, [])

console.log(res);

答案 1 :(得分:1)

我想出了一个简单的解决方案

const result = arr.reduce(function(acc, item) {
  let found = acc.find(processedItem => processedItem.employeeNumber === item.employeeNumber);
  if (found) {
    found.totalHours += item.totalHours;
    found.wages += item.wages;
  } else acc.push(item);
  return acc;

}, []);

console.log(result);

答案 2 :(得分:1)

在这里提出并回答了类似的问题:sum values in object if multiple keys are the same JS

答案的粗略解释:

1)您使用循环遍历每个项目

2)从要分组的所有属性(currentMonth,employeeNumber,caLastName,caFirstName,rate_per_hour,clientType)中生成一个“键”

3)对要求和的值求和。

这里的重要部分是将“键”和值保存到循环外部的对象中,如果您在源数组中找到具有相同“键”的另一个对象,则可以引用该对象。您需要拆分“ |”上的键字符以获取各个属性。

我链接的示例使用reduce,可以针对您的目的进行修改,但是您也可以在for循环中应用相同的逻辑。

对于较小的数据集,for往往表现优于大数据集,而reduce的设置较大则可以提高性能,但是几乎总是,算法的设计对性能的影响要比对算法的影响大一个数量级。您使用的循环方法。因此,我建议您使用最熟悉的约定,并认为您可以编写最干净,最有效的算法。

答案 3 :(得分:1)

您还可以使用:

const data = [ { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '505',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '404',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '303',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '203',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 950.4000000000001 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '202',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '500',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '400',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '300',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '201',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 864 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '200',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 } ];

const employees = data.reduce((result, employee) => {
  const key = employee.caLastName + " " + employee.caFirstName;

  if (result[key]) {
    result[key].totalHours += employee.totalHours;
    result[key].wages += employee.wages;
  } else {
    result[key] = Object.assign({}, employee);
  }
  return result;
}, {});

console.log(employees);

答案 4 :(得分:1)

请记住,您可能要使用reduce指定累加器的初始状态(在这种情况下,一个空对象听起来很合适),并且缩减函数将返回该累加器,以便可以在下一次迭代中使用它

这是我在控制台中输入的代码,可以使您朝正确的方向前进。我将您的示例对象保存到一个名为x的变量中:

x.reduce(function(acc, obj){
  // Assuming that we don't know that every entry in the array has the same currentMonth value, let's group our accumulations by month
  // This line will create a new empty object for the current month if we haven't got an entry for the month yet
  // For simple "Initialize if it's not there yet" statements, I like to use the following shorthand

  acc[obj.currentMonth] = acc[obj.currentMonth] || {};
  var monthObject = acc[obj.currentMonth];

  // Assuming that we may have array entries with different employees and that employee number is a unique way to identify them, let's make objects for each employee
  // If we don't have an entry for this employee yet in our accumulator, initialize one and save the global values
  // We will initialize hours and wages to 0 so that we have an integer defined for that value for the next step.

  monthObject[obj.employeeNumber] = monthObject[obj.employeeNumber] || { surname: obj.caLastName, firstname: obj.caFirstName, totalHours: 0, totalWages: 0 };
  var employeeEntry = monthObject[obj.employeeNumber];

  // Now, let's add the current object's values to the appropriate number fields
  employeeEntry.totalHours += obj.totalHours;
  employeeEntry.totalWages += obj.wages;

  return acc;
}, {})

希望上面的代码和注释为您提供了足够的领先优势,您可以构建自己的reduce函数,以后再也不会遇到任何麻烦。 :)

答案 5 :(得分:1)

您可以使用reduce函数迭代数组,并在reduce函数内部可以检查item是否已存在。但是时间复杂度将是n ^ 2。

let array = [ { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '505',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '404',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '303',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 633.6 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '203',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 950.4000000000001 },
  { currentMonth: 'September-2018',
    employeeNumber: '130',
    caLastName: 'Bartoletti',
    caFirstName: 'Elias',
    payrollCode: '202',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2534.4 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '500',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '400',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '300',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 576 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '201',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 24,
    wages: 864 },
  { currentMonth: 'September-2018',
    employeeNumber: '196',
    caLastName: 'Barrows',
    caFirstName: 'Felicia',
    payrollCode: '200',
    rate_per_hour: 25,
    clientType: 'Single',
    totalHours: 48,
    wages: 2304 } ];

let myArray = array.reduce((arr, value)=>{
    let index = arr.findIndex( item => item.employeeNumber == value.employeeNumber  );
    if( index >= 0 ){
       arr[index].wages += value.wages;
       arr[index].totalHours += value.totalHours;
    } else {
        arr.push(value);
    }
    console.log(index);

    return arr;
}, []);
console.log(myArray);

您还可以使用具有时间复杂度n的对象键映射(dict)来获得上述结果。 这是以下代码:

let myArray2 = array.reduce((obj, value)=>{
    if( obj[value.employeeNumber] ){
       obj[value.employeeNumber].totalHours += value.totalHours;
       obj[value.employeeNumber].wages += value.wages
    } else {
       obj[value.employeeNumber] = Object.assign({}, value );
    }
     return obj;
}, {});
let finalArrayValues = Object.values(myArray2)
console.log(finalArrayValues);