0

I have an array of objects and i want to update Total value by adding months

var arrObj=[
  {name:"ABC",Jan:0,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
    {name:"BCD",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"DEF",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"FGH",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0}
]

I am updating the value using loops and it is working also but is there any best way to put this?

var len=arrObj.length;
var Total=0;
for(var i=0;i<len;i++){
arrObj[i].Total= +arrObj[i].Jan + +arrObj[i].Feb + +arrObj[i].Mar+ +arrObj[i].Apr+ +arrObj[i].May+ +arrObj[i].Jun+ +arrObj[i].Jul+ +arrObj[i].Aug+ +arrObj[i].Sep+ +arrObj[i].Oct+ +arrObj[i].Nov+ +arrObj[i].Dec;
}
console.log(arrObj)

var arrObj=[
  {name:"ABC",Jan:0,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
    {name:"BCD",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"DEF",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"FGH",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0}
]
var len=arrObj.length;
var Total=0;
for(var i=0;i<len;i++){
arrObj[i].Total= +arrObj[i].Jan + +arrObj[i].Feb + +arrObj[i].Mar+ +arrObj[i].Apr+ +arrObj[i].May+ +arrObj[i].Jun+ +arrObj[i].Jul+ +arrObj[i].Aug+ +arrObj[i].Sep+ +arrObj[i].Oct+ +arrObj[i].Nov+ +arrObj[i].Dec;
}
console.log(arrObj)

6 Answers 6

1

You can define a function which gets the total from each object

const getTotal = obj => {
    let total = 0;
    const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    months.forEach(month => total += obj[month]);
    return total;
}

And then use it like

arrObj.forEach(obj => obj.total = getTotal(obj));
Sign up to request clarification or add additional context in comments.

1 Comment

I like this declarative approach, quite better than loop and exclude the fields that are not relevant.
0

I'm assuming you are new to programming and I'm also assuming you have complete control over the data structure so if you already know this I apologize.

There is this concept called data integrity. There are a few rules to this but the most important for the beginner to understand is what is the meaning of the data. In this case do you intact or change the data or do you just read from it?

With totals you don't interact with it directly it should be a calculation of other values and the only way to change it is by changing other values.

In JavaScript, there is the Getter which solves this problem.

Looks like this.

const obj = {
  value: 3,
  get doubleValue () {
    return this.value * 2
  }
}
obj.doubleValue // 6

In your case, you can have something like this.

{
  get Total () {
    return ...calculation
  }
}

Here is a working example

{
  name:"ABC",
  Jan:0,
  Feb:20,
  Mar:30,
  Apr:40,
  May:50,
  Jun:70,
  Jul:80,
  Aug:90,
  Sep:100,
  Oct:110,
  Nov:120,
  Dec:130,
  get Total () {
    const keys = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    let sum = 0;
    keys.forEach((key) => {
      sum += this[key]
    })
    return sum
  }
}

So If you change any of the value then call Total it will automatically update.

Comments

0

I would do something like below.

  1. Loop through array elements
  2. Filter out the unwanted keys
  3. Reduce the remaining keys to get the total

arrObj.forEach((element) => {
    element.Total = Object.keys(element).
            filter(key => key !== "name" && key !== "Total").
                reduce((acc,key) => acc + element[key], 0)
}
)

Comments

0

It can be done using reduce method:

var arrObj = [
        { name: "ABC", Jan: 0, Feb: 20, Mar: 30, Apr: 40, May: 50, Jun: 70, Jul: 80, Aug: 90, Sep: 100, Oct: 110, Nov: 120, Dec: 130, Total: 0 },
        { name: "BCD", Jan: 10, Feb: 20, Mar: 30, Apr: 40, May: 50, Jun: 70, Jul: 80, Aug: 90, Sep: 100, Oct: 110, Nov: 120, Dec: 130, Total: 0 },
        { name: "DEF", Jan: 10, Feb: 20, Mar: 30, Apr: 40, May: 50, Jun: 70, Jul: 80, Aug: 90, Sep: 100, Oct: 110, Nov: 120, Dec: 130, Total: 0 },
        { name: "FGH", Jan: 10, Feb: 20, Mar: 30, Apr: 40, May: 50, Jun: 70, Jul: 80, Aug: 90, Sep: 100, Oct: 110, Nov: 120, Dec: 130, Total: 0 }
    ];

arrObj.forEach(element => {
    let totalSum = Object.keys(element)
        .reduce((sum, key) =>{               
             return sum += parseFloat(element[key]) || 0
        }, 0);
    element.Total = totalSum;
});

console.log(arrObj);

3 Comments

The assumption that it adds any property that can be parsed to a float is great except the second time you run it.
@JasonHarwig thanks for your comment. I am sorry, could you show where it is looped the second time?
you aren't in this example, but if you were to extract this to a function it wouldn't be idempotent unless it ignored total, otherwise it'll add the total to the sum the second time.
0

You could use a loop and exclude the fields name and Total. But it would be harder to read.

var arrObj=[
  {name:"ABC",Jan:0,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
    {name:"BCD",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"DEF",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0},
   {name:"FGH",Jan:10,Feb:20,Mar:30,Apr:40,May:50,Jun:70,Jul:80,Aug:90,Sep:100,Oct:110,Nov:120,Dec:130,Total:0}
]

for(let i in arrObj){
  for(let eli in arrObj[i]){
    if(eli != "Total" && eli != "name"){
      arrObj[i].Total += arrObj[i][eli];
    }
  }
}

console.log(arrObj);

The best way would be to have an Array inside the JS-Object and use the reduce function. But I may assume that this won't apply to your use-case.

var arrObj=[
   {name:"BCD",months:[10,20,30,40,50,70,80,90,100,110,120,130],Total:0},
   {name:"DEF",months: [10,20,30,40,50,70,80,90,100,110,120,130],Total:0}
];

arrObj.forEach((e,i) => {
  arrObj[i].Total = e.months.reduce((a,b) => a+b);
});

console.log(arrObj);

Comments

0

One can define a getter property of an object where the total gets computed on every change of the properties that depends on.

In es6 one can use class and get properties to achieve this.

 Class MonthTotal {
    public Jan;
    public Feb;
    public MonthTotal(data) {
       this.Jan = data.Jan;
       this.Feb = data.Feb;
    }
    get Total() {
      return this.Jan + this.Feb;
    }
 }
 const monthData = new MonthTotal({ Jan: 10, Feb: 20});
 console.log(monthData.total); // logs :: 30

In es5 we can leverage with a simple functional getter properties call

var monthData = { 
  name:"ABC",
  Jan:0,
  Feb:20,
  Mar:30
  get total() {
    return this.Jan + this.Feb + this.Mar;
  }
}

console.log(monthData.total); // logs :: 30

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.