Luca De Acha
Luca De Acha

Reputation: 56

Angular project sum values into a new object of the same kind(typescript)

hope you're having a good day. As the title says, i'm trying calculate several objects in order to make a new one with the average values.

This is the schema

export class stats{
  assists:	number
  causedEarlySurrender:	boolean
  champLevel:	number
  combatPlayerScore:	number
  damageDealtToObjectives:	number
  damageDealtToTurrets:	number
  damageSelfMitigated:	number
  deaths:	number
  doubleKills:	number
  earlySurrenderAccomplice:	boolean
  firstBloodAssist:	boolean
  firstBloodKill:	boolean
  firstInhibitorAssist:	boolean
  firstInhibitorKill:	boolean
  firstTowerAssist:	boolean
  firstTowerKill:	boolean
  gameEndedInEarlySurrender:	boolean
  gameEndedInSurrender:	boolean
  goldEarned:	number
  goldSpent:	number
  inhibitorKills:	number
  item0:	number
  item1:	number
  item2:	number
  item3:	number
  item4:	number
  item5:	number
  item6:	number
  killingSprees:	number
  kills:	number
  largestCriticalStrike:	number
  largestKillingSpree:	number
  largestMultiKill:	number
  longestTimeSpentLiving:	number
  magicDamageDealt:	number
  magicDamageDealtToChampions:	number
  magicalDamageTaken:	number
  neutralMinionsKilled:	number
  neutralMinionsKilledEnemyJungle:	number
  neutralMinionsKilledTeamJungle:	number
  objectivePlayerScore:	number
  participantId:	number
  pentaKills:	number
  perk0:	number
  perk0Var1:	number
  perk0Var2:	number
  perk0Var3:	number
  perk1:	number
  perk1Var1:	number
  perk1Var2:	number
  perk1Var3:	number
  perk2:	number
  perk2Var1:	number
  perk2Var2:	number
  perk2Var3:	number
  perk3:	number
  perk3Var1:	number
  perk3Var2:	number
  perk3Var3:	number
  perk4:	number
  perk4Var1:	number
  perk4Var2:	number
  perk4Var3:	number
  perk5:	number
  perk5Var1:	number
  perk5Var2:	number
  perk5Var3:	number
  perkPrimaryStyle:	number
  perkSubStyle:	number
  physicalDamageDealt:	number
  physicalDamageDealtToChampions:	number
  physicalDamageTaken: number
  playerScore0: number
  playerScore1: number
  playerScore2: number
  playerScore3: number
  playerScore4: number
  playerScore5: number
  playerScore6: number
  playerScore7: number
  playerScore8: number
  playerScore9: number
  quadraKills: number
  sightWardsBoughtInGame: number
  teamEarlySurrendered:	boolean
  timeCCingOthers: number
  totalDamageDealt: number
  totalDamageDealtToChampions: number
  totalDamageTaken: number
  totalHeal: number
  totalMinionsKilled: number
  totalPlayerScore: number
  totalScoreRank: number
  totalTimeCrowdControlDealt: number
  totalUnitsHealed: number
  tripleKills: number
  trueDamageDealt: number
  trueDamageDealtToChampions: number
  trueDamageTaken: number
  turretKills: number
  unrealKills: number
  visionScore: number
  visionWardsBoughtInGame: number
  wardsKilled: number
  wardsPlaced: number
  win:	boolean
}

So i get this data in an array of objects, like this.

0: {assists: 0, causedEarlySurrender: false, champLevel: 18, combatPlayerScore: 0, damageDealtToObjectives: 60241, …}
1: {assists: 2, causedEarlySurrender: false, champLevel: 18, combatPlayerScore: 0, damageDealtToObjectives: 7592, …}
2: {assists: 0, causedEarlySurrender: false, champLevel: 16, combatPlayerScore: 0, damageDealtToObjectives: 8982, …}

I was trying a few things, but i can't find a way of doing this automatically, meaning not to have to type every key name.

This is what i have so far:

  meanStats(){
    let iterator = 0;
    this.stats.forEach((m, i, array)=>{
      iterator ++;
      for (let [key, value] of Object.entries(m)) {
        console.log(key, value);
        switch (value) {
          case Boolean:
            if(key == "win"){
              this.wins += value//if true should compute as 1 and if its not should be 0
            }
            if(key == "gameEndedInSurrender"){
              this.surrenders += value
            }
            else{
              break
            }
            break;
          case Number://meanStat is the new object 
          this.meanStat.key += value
            break;
          default:
            break;
        }
    }
      });

    
    }

The idea would be to access each keyname and value, check if its a boolean or a number,(lots of cases missing in case it's a boolean) sum that value on the correct key of the new object. After that divide all values by the iterator and i should have an average. Does not work, because key is not a known value of the object.

Any help would be appreciated. As allways thanks a lot.

Upvotes: 0

Views: 130

Answers (2)

Luca De Acha
Luca De Acha

Reputation: 56

I'm posting the result, it might be usefull to some of you. I still need to handle booleans separately, so it's not 100% complete. Some of the values don't need to be averaged, others use a max value, so things got somewhat complex. I was able to use my object schema, so that's good.

Here's the code:

meanStats(){
    
    this.stats.forEach((m, i, array)=>{
      for (let [key, value] of Object.entries(m)) {

   //setting everything to default
        if(typeof(this.meanStat[key])=="undefined" && typeof(value)=="number"){
          this.meanStat[key] = 0
        }else if(typeof(this.meanStat[key])=="undefined" && typeof(value)=="boolean"){
          this.meanStat[key] = false
//filtering by number types              
        }
        if (typeof(value) == "number"){
          let aux: number = this.meanStat[key]
          if (key == "largestCriticalStrike" || key == "largestKillingSpree"||key == "largestMultiKill"){
            if(value > this.meanStat[key]){
              this.meanStat[key] = value
            }
          }else if (key == "doubleKills"|| key=="tripleKills"|| key == "quadraKills" || key=="pentakills"){
            switch (key) {
//decided to make separate variables for this ones and also to have the average values.
              case "doubleKills":
                this.doublekills +=value
                aux+=value
                this.meanStat[key] = aux                
                break;
              case "tripleKills":
                this.triplekills +=value
                aux+=value
                this.meanStat[key] = aux  

                break;
              case  "quadraKills":
                this.quadrakills +=value
                aux+=value
                this.meanStat[key] = aux  
                break;
              case "pentakills":
                this.pentakills +=value
                aux+=value
                this.meanStat[key] = aux  
                break;
            
              default:
                break;
            }
          }else{
            aux+=value;
            this.meanStat[key] = aux;
          }
        }else{
          switch (key) {
//need to handle other booleans, have not done that yet that's why is only one case
            case "win":
                if(value == true){
                  this.wins ++
                }
              break;
          
            default:
              break;
          }
        }
    }
      });
//average every number except largestCriticalStrike
    Object.keys(this.meanStat).forEach((key) => {
      if (typeof(this.meanStat[key])== "number"){
        if(key != "largestCriticalStrike" ){
          this.meanStat[key] = this.meanStat[key]/this.stats.length
        }        
      }      
    })
    console.log(this.meanStat)   
    console.log(this.wins)   
    } 
  
}

Code works, but if someone knows how to do this in a better way, feel free to post your own answer. Have a good day. Oh, and thx to @Arun Mohan for it's help.

Upvotes: 0

Arun Mohan
Arun Mohan

Reputation: 1227

You can try something like this. But you need to handle boolean separately.

const obj = {};



let a= [
   {assists: 0, champLevel: 18, combatPlayerScore: 0, damageDealtToObjectives: 60241},
    {assists: 2, champLevel: 18, combatPlayerScore: 0, damageDealtToObjectives: 60241},
     {assists: 4, champLevel: 18, combatPlayerScore: 0, damageDealtToObjectives: 60241}
]

a.forEach( item => {
  Object.keys(item).forEach(key => {
    if (obj[key]) {
      obj[key]+= item[key];
    } else {
      obj[key]= item[key];
    }
  });
});
 Object.keys(obj).forEach((key) => obj[key] = obj[key]/a.length);

Upvotes: 1

Related Questions