0

I want to add some object values from an object array based on another object key. I want to know how this can be achieved from plain Javascript or by using a helper library like lodash.

I have already tried using lodash's _.groupBy and Array.prototype.reduce(), but haven't got it to work. Here is what the data looks like:

{
  "2019-01-04": [
    {
        "payments": [
            {
                "sum": "12",
                "currency": "€"
            }
        ]
    }
  ],

  "2019-01-06": [
    {
        "payments": [
            {
                "sum": "50",
                "currency": "€"
            },
            {
                "sum": "30",
                "currency": "£"
            },
            {
                "sum": "40",
                "currency": "Lek"
            },
            {
                "sum": "2",
                "currency": "£"
            },
            {
                "sum": "60",
                "currency": "£"
            }
        ]
    }
  ]
}

I expect a result where the sum property has the sum of all currencies of the same type from that date:

{
  "2019-01-04": [
    {
        "payments": [
            {
                "sum": "12",
                "currency": "€"
            }
        ]
    }
  ],

  "2019-01-06": [
    {
        "payments": [
            {
                "sum": "50",
                "currency": "€"
            },
            {
                "sum": "92",
                "currency": "£"
            },
            {
                "sum": "40",
                "currency": "Lek"
            }
        ]
    }
  ]
}
3
  • 4
    Please add your attempts to the question... Commented Jan 7, 2019 at 14:14
  • To recap: get the sum if a currency exists more than once on a certain date? Commented Jan 7, 2019 at 15:14
  • Do you know forehand what currencies you have? Commented Jan 8, 2019 at 11:05

2 Answers 2

2
const result = {};
Object.keys(input).forEach(date => {
    result[date] = [{ }];
    result[date][0].payments = input[date][0].payments.reduce((payments, c) => {
        const grp = payments.find(p => p.currency === c.currency);
        grp ? grp.sum = +grp.sum + +c.sum : payments.push(c);
        return payments;
    }, []);
});
Sign up to request clarification or add additional context in comments.

1 Comment

I like your solution as it's much cleaner then mine :) thanks!
0

Given data structure you provided, using following method gives desired output:

function sumByCurrency(history) {
    _.forOwn(history, value => {
        const newPayments = [];

        _.forEach(value["0"].payments, v => {
            let existingPayment = _.find(
                newPayments,
                newPayment => newPayment && newPayment.currency === v.currency
            );

            if (existingPayment) {
                let existingSum = +existingPayment.sum;
                let incomingSum = +v.sum;

                existingSum += incomingSum ? incomingSum : 0;

                existingPayment.sum = "" + existingSum;
            } else {
                newPayments.push({
                    currency: v.currency,
                    sum: v.sum ? v.sum : 0
                });
            }
        });

        value["0"].payments = newPayments;
    });

    return history;
}

Use it passing your object, say you call it paymentHistory to sumByCurrency function like this:

sumByCurrency(paymentHistory);

Please note: You probably want to make some fallbacks/make sure it doesn't break if value["0"].payments is not available.

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.