2

I have array of objects like this and require to calculate running total(accumulate sum) dynamically for N keys.

  let a = [
  {"subject":  "Civil", "a": 100, "b":50, "c":100 },
  {"subject":  "aero",  "a": 200, "b":130,"c":100 },
  {"subject":  "tribe", "a": 100, "b":100,"c":600 },
  {"subject":  "solen", "a": 400, "b":150,"c":100},
  {"subject":  "space", "a": 100, "b":100,"c":900 }
];

Required Output as below :

[
{"subject": "Civil", "a": 100, "b": 50,  "c": 100},
{"subject": "aero",  "a": 300, "b": 180, "c": 200},
{"subject": "tribe", "a": 400, "b": 280, "c": 800},
{"subject": "solen", "a": 800, "b": 430, "c": 900},
{"subject": "space"," a": 900, "b": 530, "c": 1800}]

I tried below using MAP as below :

let b = a.map( x => ({...x,"a":a1+=x.a,"b":b1+=x.b,"c":c1+=x.c}) )

I want to achieve it dynamically without writing a, b, c.

1
  • 1
    what is expected output? Commented Nov 30, 2021 at 0:29

2 Answers 2

2

If you want to cumulatively sum every property other than subject, you can do so by mapping the array to new values, keeping an object reference for each running total as you go

const a = [{"subject":"Civil","a":100,"b":50,"c":100},{"subject":"aero","a":200,"b":130,"c":100},{"subject":"tribe","a":100,"b":100,"c":600},{"subject":"solen","a":400,"b":150,"c":100},{"subject":"space","a":100,"b":100,"c":900}]

const cf = {} // store running totals in here
const b = a.map(({ subject, ...props }) => ({
  subject,
  ...Object.fromEntries(Object.entries(props).map(([ key, val ]) => [
    key,
    cf[key] = (cf[key] ?? 0) + val // value is the result of the assignment
  ]))
}))

console.log(b)
.as-console-wrapper { max-height: 100% !important; }

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

2 Comments

can I add an Initial value as well?
@RajseGodia you can initialise cf to whatever you want if that's what you mean, eg const cf = { a: 500, b: -2 }
0

You can use a combination of .map(), .slice() and .reduce() array methods as follows:

let a = [
  {"subject":  "Civil", "a": 100, "b":50, "c":100 },
  {"subject":  "aero",  "a": 200, "b":130,"c":100 },
  {"subject":  "tribe", "a": 100, "b":100,"c":600 },
  {"subject":  "solen", "a": 400, "b":150,"c":100},
  {"subject":  "space", "a": 100, "b":100,"c":900 }
];

let b = a.map((x,i) => ({
    subject:x.subject,
    a:a.slice(0,i+1).map(({a}) => a).reduce((x,y) => x + y),
    b:a.slice(0,i+1).map(({b}) => b).reduce((x,y) => x + y),
    c:a.slice(0,i+1).map(({c}) => c).reduce((x,y) => x + y)
}));

console.log( b );

Alternatively, this can be done without reference to any particular properties as follows:

let a = [
  {"subject":  "Civil", "a": 100, "b":50, "c":100, "zz":0},
  {"subject":  "aero",  "a": 200, "b":130,"c":100, "zz":40},
  {"subject":  "tribe", "a": 100, "b":100,"c":600, "zz":0},
  {"subject":  "solen", "a": 400, "b":150,"c":100, "zz":60},
  {"subject":  "space", "a": 100, "b":100,"c":900, "zz":200}
];

let b = a.map((val, i) => ({
        ...val,
        //introduce a temp property 'index'
        index: i + 1 
    }))
    .map(({
        subject,
        index,
        ...rest
    }) => ({
        subject,
        ...Object.keys(rest).reduce((obj, cur) => ({
            ...obj,
            ...{
                //use temp propterty to compute running total for every
                //property but 'subject', 
                [cur]: a.slice(0, index).map(v => v[cur]).reduce((x, y) => x + y)
            }
        }), {})
    }));   

console.log( b );

2 Comments

i want to achieve it dynamically i.e. don't want to hard code a,b,c
No problem. The second option should take care of that.

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.