Help transforming array of objects in simplified array

Hi there guys, ive been struggling all the weekend over the following issue. i have an array of objects that represents accountance values and amounts.Here is the structure of an item of that array:

objt:{
  ref:12345,
  amount:452012,
  typeOp:"FRAAC",
  compteD:675000,
  compteC:null
}

Some of those objects share the same properties.i would like to be able to get those objects which share the same ref,typeOp and CompteD or CompteC, find their amounts and sum them up and get a new object inside an new array of objects.

To illustrate let’s say i have the following array:

[{ref:123,amount:35000,typeOp:"AAC",compteD:233000,compteC:null},{ref:123,amount:250000,typeOp:"FRAAC",compteD:675000,compteC:null},{ref:123,amount:3240,typeOp:"FRAAC",compteD:675000,compteC:null},{ref:123,amount:20000,typeOp:"FRAAC",compteD:675000,compteC:null},{ref:123,amount:35000,typeOp:"AAC",compteD:null,compteC:562115},{ref:123,amount:250000,typeOp:"FRAAC",compteD:null,compteC:562115},{ref:123,amount:3240,typeOp:"AAC",compteD:null,compteC:562115},{ref:123,amount:20000,typeOp:"AAC",compteD:null,compteC:562115},]

i’d like to reduce this array based on the typeOp the ref and the compteD or compteC. the end result should be the following:

[{ref:123,amount:35000,typeOp:"AAC",compteD:233000,compteC:null},{ref:123,amount:273240/*which is the sum of all the objects of the previous array which share the same typeOp,compteD and ref number*/,typeOp:"AAC",compteD:675000,compteC:null},{ref:123,amount:35000,typeOp:"AAC",compteD:null,compteC:562115},{ref:123,amount:273240/*which is the sum of all the objects of the previous array which share the same typeOp,compteC and ref number*/,typeOp:"FRAAC",compteD:null,compteC:562115}]

Can you help me figure this out as the array could have different ref numbers(a ref numbers identifies a particular operation).

Thanks.

R = require('ramda');

const groupedAndSummed = R.compose(
    R.map(R.reduce(function(acc, v) {
        return R.assoc('amount', (acc.amount || 0) + v.amount, v);
    }, {})),
    R.values,
    R.groupBy(R.compose(
        R.join(''),
        R.reject(R.isNil),
        R.props(['ref', 'typeOp', 'compteD', 'compteC'])
    ))
)(arrayOfObjects);

In case the data is coming from a mongo database and performance is an issue, you should use the aggregation pipeline.

Thanks but the data doesnt come from mongo.It is the result of a method call that disects an xls file and generate the accountancy docs.

ramda is like lodash or underscore but the functions are better suited for function composition.

Ok…could you implement it using the case when data is given as an object resulting from a meteor method call?

How is the data structured your meteor method returns?

the method returns an array of object much like the following.

[{ref:123,amount:35000,typeOp:"AAC",compteD:233000,compteC:null},
{ref:123,amount:250000,typeOp:"FRAAC",compteD:675000,compteC:null},
{ref:123,amount:3240,typeOp:"FRAAC",compteD:675000,compteC:null},
{ref:123,amount:20000,typeOp:"FRAAC",compteD:675000,compteC:null},
{ref:123,amount:35000,typeOp:"AAC",compteD:null,compteC:562115},
{ref:123,amount:250000,typeOp:"FRAAC",compteD:null,compteC:562115},
{ref:123,amount:3240,typeOp:"FRAAC",compteD:null,compteC:562115},
{ref:123,amount:20000,typeOp:"FRAAC",compteD:null,compteC:562115}]

But the function should be able to treat also the case when there is another ref number.
The ref propertie is used ot identify the operation to which an object belongs

const arrayOfObjects = [
    {ref:123,amount:35000,typeOp:"AAC",compteD:233000,compteC:null},
    // ...
    {ref:123,amount:20000,typeOp:"FRAAC",compteD:null,compteC:562115}]
];

const groupAndSum = R.compose(
    R.map(R.reduce(function(acc, v) {
        return R.assoc('amount', (acc.amount || 0) + v.amount, v);
    }, {})),
    R.values,
    R.groupBy(R.compose(
        R.join(''),
        R.reject(R.isNil),
        R.props(['ref', 'typeOp', 'compteD', 'compteC'])
    ))
);

const groupedAndSummed = groupAndSum(arrayOfObjects);

Thanks man,i am trying it ASAP

But the function should be able to treat also the case when there is another ref number.

Should objects with the same ref and typeOp, compteD or compteC be grouped together or should they be first grouped by ref and then by the other properties?

Objects with the same ref and typeOp and compteD/compteC should be grouped together.if those exist in the array more than once then they should be reduced

Does the code above take care of that too?

Well still no luck with your solution…did you see my other posts?

What exactly does not work?

, lemme try again.in 5 min tops ill write the whole code and results i get in my console.

So here i first thought it was related to my array so i re-structured if in a more simple way

[{ref:123,amount:35000,typeOp:"AAC",ou:"C",compte:233000}]

the propertie ou i added is to lemme know if its an operation to be scored in the DEBIT or CREDIT section,hence the removal of the two properties compteC and compteD

furthermore i also had two amount properties amountD and amountC which i fused into the single amount.After firing up the code it reduces my array of ten objects to five.It divides my array right in the middle because the meteor call made earlier to get that array automatically sorts it by ref so that i have all DEBIT details which are part of the same operation in the first rows and the CREDIT details come next.

[{ref:123,amount:35000,typeOp:"AAC",ou:"D",compte:233000},
{ref:123,amount:5000,typeOp:"FRAAC",ou:"D",compte:675000},
{ref:123,amount:3000,typeOp:"FRAAC",ou:"D",compte:675000},
{ref:123,amount:35000,typeOp:"AAC",ou:"C",compte:562115},
{ref:123,amount:5000,typeOp:"FRAAC",ou:"C",compte:562115},
{ref:123,amount:3000,typeOp:"FRAAC",ou:"C",compte:562115}]

It just cuts the DEBIT part off.

[{ref:123,amount:**70000**,typeOp:"AAC",ou:"C",compte:562115},
{ref:123,amount:**10000**,typeOp:"FRAAC",ou:"C",compte:562115},
{ref:123,amount:**6000**,typeOp:"FRAAC",ou:"C",compte:562115}]

and it doubles the amount on this part,this is great but it should only double it if the typeOp,the compte and the ref is the same (which would mean the type of the operation is the same be it debit or credit).

i should still have both DEBIT and CREDIT side of the array, but with the repeating objects of those parts reduced to one

thanks

i managed to get the results i want, thanks a lot for introducing me to ramda.it makes a fine addition to my library.