1

So I have an array of objects that looks like this.

const myArray = [
  {
    values: [
      { date: "2018-11-02", "value1": 3, "value2": 5 },
      { date: "2018-11-01", "value1": 8, "value2": 9 },
      { date: "2018-10-31", "value1": 4, "value2": 10 },
    ],
    customer: "Customer One"
  },
  {
    values: [
      { date: "2018-11-02", "value1": 3 },
      { date: "2018-11-01", "value1": 5 },
      { date: "2018-10-31", "value1": 8 },
    ],
    customer: "Customer Two"
  }
];

All values of an object should be summed(by date) and then result as the value for the customer in the new object

What I want is it to look like this:

result = [
  { date: "2018-11-02", "Customer One": 8, "Customer Two": 3 },
  { date: "2018-11-01", "Customer One": 17, "Customer Two": 5 },
  { date: "2018-10-31", "Customer One": 14, "Customer Two": 8 },
]

I have working code for this but it feels way too complicated for what I need but I can't wrap my head around an easier way for some reason.

Here's my code (also on codesandbox: https://codesandbox.io/s/zvlpm167x):

const myArray = [
  {
    values: [
      { date: "2018-11-02", "value1": 3, "value2": 5 },
      { date: "2018-11-01", "value1": 8, "value2": 9 },
      { date: "2018-10-31", "value1": 4, "value2": 10 },
    ],
    customer: "Customer One"
  },
  {
    values: [
      { date: "2018-11-02", "value1": 3 },
      { date: "2018-11-01", "value1": 5 },
      { date: "2018-10-31", "value1": 8 },
    ],
    customer: "Customer Two"
  }
];

const flatArray = myArray.flat();

const sumObjectKeysExceptDate = object => Object.keys(object).reduce((sum, key) => {
  if (!Number.isNaN(parseInt(object[key], 10)) && key !== 'date') {
    return sum + parseInt(object[key], 10);
  }
  return sum;
}, 0);

const result = flatArray
  .reduce((acc, row) => [...acc, ...row.values.map(value => ({ [row.customer]: sumObjectKeysExceptDate(value), date: value.date }))], [])
  .reduce((acc, row) => {
    if (acc.find(innerrow => innerrow.date === row.date)) {
      return acc.map((innerrow) => {
        if (innerrow.date === row.date) {
          return { ...innerrow, ...row };
        }
        return innerrow;
      });
    }
    return [...acc, row];
  }, []);

console.log(result)

1 Answer 1

1

Try following

  • Create an object with date as key and corresponding resulting object as value. And using Object.values get the final result
  • To build the object, use Array.reduce on outer array and for each value of inner array, check whether the entry for date exists or not in object. If it exists update it else create a new entry in object.
  • For each object in inner array, sum the values of all keys except date and set it in object corresponding to the customer name key.

const myArray = [{values: [{ date: "2018-11-02", "value1": 3, "value2": 5 },{ date: "2018-11-01", "value1": 8, "value2": 9 },{ date: "2018-10-31", "value1": 4, "value2": 10 },],customer: "Customer One"},{values: [{ date: "2018-11-02", "value1": 3 },{ date: "2018-11-01", "value1": 5 },{ date: "2018-10-31", "value1": 8 },],customer: "Customer Two"}];

let result = Object.values(myArray.reduce((a,c) => {
  c.values.forEach(({date, ...rest}) => {
    a[date] = a[date] || {date};
    a[date][c.customer] = Object.values(rest).reduce((d,e) => d + e);
  });
  return a;
}, {}));
console.log(result);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.