получение отдельных элементов с суммой из массива объектов - PullRequest
0 голосов
/ 26 сентября 2018

Я действительно искал и не могу найти правильный ответ.У меня есть массив объектов:

[ { 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 голосов
/ 26 сентября 2018

Вы можете перебирать массив, используя функцию Reduce, а внутри функции Reduce вы можете проверить, существует ли элемент уже или нет.Но для этого временная сложность будет 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);

Вы также можете достичь вышеуказанного результата, используя отображение ключа объекта (dict) со временной сложностью n.Вот следующий код:

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);
0 голосов
/ 26 сентября 2018

Помните, что с помощью 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;
}, {})

Надеемся, что приведенный выше код и комментарии обеспечат вам достаточный старт, чтобы вы могли без проблем создавать свои функции сокращения в будущем.,:)

0 голосов
/ 26 сентября 2018

Вы также можете использовать:

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);
0 голосов
/ 26 сентября 2018

Здесь задается аналогичный вопрос: сумма значений в объекте, если несколько ключей одинаковы. JS

Грубое объяснение ответа:

1)Вы используете цикл для прохождения каждого элемента

2) Создайте «ключ» из всех свойств, по которым вы хотите сгруппировать (currentMonth, employeeNumber, caLastName, caFirstName, rate_per_hour, clientType)

3) Суммируйте значения, которые вы хотите суммировать.

Важной частью здесь является то, что вы сохраняете «ключ» и значение в объекте вне цикла, на который вы можете сослаться, если вы найдете другой объект в исходном массиве с тем же «ключом».Вам нужно будет разделить ключи на "|"символ, чтобы получить обратно отдельные свойства.

В примере, который я ссылаюсь, используется Reduce, который вы можете изменить для своих целей, но вы также можете применить ту же логику в цикле for.

Для небольших наборов данных for имеет тенденцию опережать уменьшение, а с большими наборами reduce повышает производительность, но почти всегда разработка алгоритма оказывает на порядок большее влияние на производительность, чем зацикливаниеметод, который вы используете.Поэтому я бы порекомендовал использовать соглашение, которое вам наиболее удобно, и на ваш взгляд, вы можете написать самый чистый и эффективный алгоритм.

0 голосов
/ 26 сентября 2018

Я придумал простое решение

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);
0 голосов
/ 26 сентября 2018

Вы можете использовать сокращение и агрегирование данных, таких как

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);
...