2
votes

Comment additionner les propriétés des objets à l'intérieur des objets?

J'essaie de faire la somme du total des matchs et des participants de chaque coupe dans cet objet:

var cups_result = {
  "Total_Cup_1": {
    matches: 72,
    participants: 6740,
  },
  "Total_Bronze": {
    matches: 57,
    participants: 5443,
  },
}

Je ne sais pas comment additionner les propriétés lorsque l'objet a un autre objet à l'intérieur ( désolé, je ne l'ai pas encore appris);

Je veux avoir un nouvel objet avec les résultats de chaque match de coupe et le nombre total de participants. Et aussi le total des matchs et des participants de chaque catégorie pour toutes les coupes à l'exception de la cup_5 car il n'y a qu'une seule catégorie.

Quelque chose comme:

Total des matchs de la Coupe_1: 72 p >

Nombre total de participants à la Coupe_1: 6740

Total des matchs de bronze (toutes les coupes): 57;

Total des participants au bronze (toutes les coupes): 5443

Exemple nouvel objet avec les résultats:

{
    "Cup_1": {
        "bronze": {
            "matches": 3,
            "participants": 289
        },
        "silver": {
            "matches": 20,
            "participants": 1874
        },
        "gold": {
            "matches": 35,
            "participants": 3227
        },
        "platinum": {
            "matches": 3,
            "participants": 294
        },
        "diamond": {
            "matches": 5,
            "participants": 482
        },
        "ace": {
            "matches": 6,
            "participants": 574
        }
    },
    "Cup_2": {
        "bronze": {
            "matches": 17,
            "participants": 1609
        },
        "silver": {
            "matches": 46,
            "participants": 4408
        },
        "gold": {
            "matches": 157,
            "participants": 14391
        },
        "platinum": {
            "matches": 0,
            "participants": 0
        },
        "diamond": {
            "matches": 5,
            "participants": 469
        },
        "ace": {
            "matches": 10,
            "participants": 959
        }
    },
    "Cup_3": {
        "bronze": {
            "matches": 35,
            "participants": 3358
        },
        "silver": {
            "matches": 96,
            "participants": 9069
        },
        "gold": {
            "matches": 313,
            "participants": 29527
        },
        "platinum": {
            "matches": 10,
            "participants": 960
        },
        "diamond": {
            "matches": 16,
            "participants": 1538
        },
        "ace": {
            "matches": 45,
            "participants": 4280
        }
    },
    "Cup_4": {
        "bronze": {
            "matches": 2,
            "participants": 187
        },
        "silver": {
            "matches": 8,
            "participants": 742
        },
        "gold": {
            "matches": 37,
            "participants": 3416
        },
        "platinum": {
            "matches": 0,
            "participants": 0
        },
        "diamond": {
            "matches": 2,
            "participants": 196
        },
        "ace": {
            "matches": 3,
            "participants": 290
        }
    },
    "Cup_5": {
        "bronze": {
            "matches": 89,
            "participants": 1638
        }
    }
}

J'ai lu que cette somme de propriétés d'objets pouvait être faite avec .map mais je ne sais pas comment utiliser correctement la carte avec des objets.

Si quelqu'un pouvait être gentil de m'aider, je serais reconnaissant!


8 commentaires

Qu'est-ce que tu as essayé jusque-là?


Désolé, j'ai modifié la question pour indiquer que j'essaie de faire la somme des propriétés des objets à l'intérieur des objets!


Je ne sais pas comment accéder aux objets comme "bronze", "argent" et ainsi, pour obtenir les vaues totales.


@RogerHN utilise l'instruction for in pour boucler sur la clé d'un objet.


J'ai essayé ceci: for (var c in cups) {console.log (c)} mais il n'enregistre que les noms de chaque objet comme "Cup_1"


La boucle imbriquée pour peut aider dans ce cas. for (var c in cups) {for (let medal in cups [c]) {console.log (cups [c] [medal] ["" ​​matches "], cups [c] [medal] [" participants "]) }}


Vous pouvez facilement énumérer toutes les propriétés d'un objet à l'aide de la fonction Object.entries (YOUR_OBJECT_HERE). Cela vous donnera un tableau de tableaux qui sont des paires clé-valeur. À partir de là, vous devriez être en mesure d'atteindre votre objectif.


@JakubRusilko Ouais mais cela semble compliquer encore plus le résultat :(


6 Réponses :


2
votes

La boucle imbriquée for sera utile pour récupérer les correspondances et les champs des participants à partir de la var.

for (var c in cups) { 
   for ( let medal in cups[c] ) { 
        console.log(cups[c][medal]["matches"], cups[c][medal]["participants"]);
   } 
} 


2 commentaires

Cela fonctionne, j'ai accès aux données, mais comment les résumer comme je l'ai dit dans la question? C'est le problème :(


@RogerHN "+" est utilisé pour additionner deux nombres en javascript. J'espère que ce serait utile.



2
votes

Créez un objet vide pour result. Utilisez ensuite forEach () pour parcourir toutes les coupes. Et stockez le résultat dans l'objet vide.

let data = {
    "Cup_1": {
        "bronze": {
            "matches": 3,
            "participants": 289
        },
        "silver": {
            "matches": 20,
            "participants": 1874
        },
        "gold": {
            "matches": 35,
            "participants": 3227
        },
        "platinum": {
            "matches": 3,
            "participants": 294
        },
        "diamond": {
            "matches": 5,
            "participants": 482
        },
        "ace": {
            "matches": 6,
            "participants": 574
        }
    },
    "Cup_2": {
        "bronze": {
            "matches": 17,
            "participants": 1609
        },
        "silver": {
            "matches": 46,
            "participants": 4408
        },
        "gold": {
            "matches": 157,
            "participants": 14391
        },
        "platinum": {
            "matches": 0,
            "participants": 0
        },
        "diamond": {
            "matches": 5,
            "participants": 469
        },
        "ace": {
            "matches": 10,
            "participants": 959
        }
    },
    "Cup_3": {
        "bronze": {
            "matches": 35,
            "participants": 3358
        },
        "silver": {
            "matches": 96,
            "participants": 9069
        },
        "gold": {
            "matches": 313,
            "participants": 29527
        },
        "platinum": {
            "matches": 10,
            "participants": 960
        },
        "diamond": {
            "matches": 16,
            "participants": 1538
        },
        "ace": {
            "matches": 45,
            "participants": 4280
        }
    },
    "Cup_4": {
        "bronze": {
            "matches": 2,
            "participants": 187
        },
        "silver": {
            "matches": 8,
            "participants": 742
        },
        "gold": {
            "matches": 37,
            "participants": 3416
        },
        "platinum": {
            "matches": 0,
            "participants": 0
        },
        "diamond": {
            "matches": 2,
            "participants": 196
        },
        "ace": {
            "matches": 3,
            "participants": 290
        }
    },
    "Cup_5": {
        "bronze": {
            "matches": 89,
            "participants": 1638
        }
    }
}



function sumOfCup(obj,cupNos,cuptypes){
  let result = {};
  Object.keys(obj).forEach(a => {
    Object.keys(obj[a]).forEach(x => {
    if(result[`Total_${x}`]){
      result[`Total_${x}`].matches += obj[a][x].matches;
      result[`Total_${x}`].participants += obj[a][x].participants;
    }
    else result[`Total_${x}`] = {...obj[a][x]};
  })
  result[`Total_${a}`] = Object.values(obj[a]).reduce((ac,a)=>{
    ac.matches += a.matches 
    ac.participants += a.participants;
    return ac;
  },{matches:0,participants:0})
  })

  
 
  return result
  
  
  
}
console.log(data);
console.log(sumOfCup(data))


1 commentaires

Saint! C'est une fonction complexe sérieuse! Je ne sais pas encore écrire des choses comme ça! Je vais essayer ici et essayer de comprendre comment cela fonctionne! Merci beaucoup!



2
votes

Je séparerais toujours les totaux par tasse des totaux par médaille, et peut-être ajouterais-je également un total général (puisque nous y sommes):

const data = {"Cup_1": {"bronze": {"matches": 3,"participants": 289},"silver": {"matches": 20,"participants": 1874},"gold": {"matches": 35,"participants": 3227},"platinum": {"matches": 3,"participants": 294},"diamond": {"matches": 5,"participants": 482},"ace": {"matches": 6,"participants": 574}},"Cup_2": {"bronze": {"matches": 17,"participants": 1609},"silver": {"matches": 46,"participants": 4408},"gold": {"matches": 157,"participants": 14391},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 5,"participants": 469},"ace": {"matches": 10,"participants": 959}},"Cup_3": {"bronze": {"matches": 35,"participants": 3358},"silver": {"matches": 96,"participants": 9069},"gold": {"matches": 313,"participants": 29527},"platinum": {"matches": 10,"participants": 960},"diamond": {"matches": 16,"participants": 1538},"ace": {"matches": 45,"participants": 4280}},"Cup_4": {"bronze": {"matches": 2,"participants": 187},"silver": {"matches": 8,"participants": 742},"gold": {"matches": 37,"participants": 3416},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 2,"participants": 196},"ace": {"matches": 3,"participants": 290}},"Cup_5": {"bronze": {"matches": 89,"participants": 1638}}}

const cupTotals = {}, 
      medalTotals = {}, 
      grandTotal = { matches: 0, participants: 0 };
for (const cup in data) {
    cupTotals[cup] = { matches: 0, participants: 0 };
    for (let medal in data[cup]) {
        const {matches, participants} = data[cup][medal];
        if (cup === "Cup_5" && medal === "bronze") medal = "junior";
        cupTotals[cup].matches += matches;
        cupTotals[cup].participants += participants;
        if (!medalTotals[medal]) medalTotals[medal] = { matches: 0, participants: 0 };
        medalTotals[medal].matches += matches;
        medalTotals[medal].participants += participants;
        grandTotal.matches += matches;
        grandTotal.participants += participants;
    }
}
const results = { cupTotals, medalTotals, grandTotal };

console.log(results);


13 commentaires

C'est encore mieux, merci beaucoup aussi! Je vais essayer ici et essayer de comprendre comment fonctionne cette fonction! J'ai de sérieuses difficultés à comprendre les manipulations d'objets et de tableaux.


Aucun problème. N'hésitez pas à poser des questions sur les morceaux de code qui nécessitent des éclaircissements.


Dans cette fonction, il est possible d'exclure le "Cup_5" de la somme?


Bien sûr, quelle est la particularité de Cup_5 si je peux demander?


C'est une catégorie junior, avec une seule médaille (que j'ai aussi représentée avec du bronze, mais ce n'est pas une médaille de bronze).


OK, j'ai mis à jour le code pour cela et ajouté un total de subventions. Cup_5 est complètement ignoré de toutes les statistiques.


Alternativement, vous pouvez faire de la logique pour produire une statistique sur une médaille "junior" lorsqu'elle est Cat_5. Serait-ce mieux? Si c'est le cas, j'ajouterai le code pour cela ...


Bien sûr que ce sera le cas, sinon je le ferai à la main :)


De plus, vous m'avez époustouflé avec cette fonction! C'est parfait, le résultat exact que je recherchais. J'étudierai morceau par morceau pour mieux le comprendre! Je ne connaissais pas l'instruction continue , seulement la break (je commence la deuxième année d'université en informatique).


Maintenant modifié pour prendre en compte Cat_5, mais en changeant "bronze" en "junior" à la volée. Laissez-moi savoir ce que vous pensez. Si pire, je vais annuler le changement de cap;)


Mieux encore, vous méritez une médaille! Merci beaucoup de m'aider à résoudre ce problème! J'ai beaucoup appris avec votre logique!


votre code n'est générique pour aucun type de médaille car il teste spécifiquement if value == 'bronze etc' ..


@GauravSaraswat, veuillez lire les commentaires ci-dessus. Ce if est là pour faire face à un besoin très particulier du PO exprimé ici. Sans cela, cela fonctionne bien aussi.



2
votes

Vous pouvez utiliser Object.keys , Object.values ​​ et la déstructuration pour cela - ci-dessous renvoie un résumé de chaque tasse:

const cup_data = {
  "Cup_1": {
    "bronze": {
      "matches": 3,
      "participants": 289
    },
    "silver": {
      "matches": 20,
      "participants": 1874
    },
    "gold": {
      "matches": 35,
      "participants": 3227
    },
    "platinum": {
      "matches": 3,
      "participants": 294
    },
    "diamond": {
      "matches": 5,
      "participants": 482
    },
    "ace": {
      "matches": 6,
      "participants": 574
    }
  },
  "Cup_2": {
    "bronze": {
      "matches": 17,
      "participants": 1609
    },
    "silver": {
      "matches": 46,
      "participants": 4408
    },
    "gold": {
      "matches": 157,
      "participants": 14391
    },
    "platinum": {
      "matches": 0,
      "participants": 0
    },
    "diamond": {
      "matches": 5,
      "participants": 469
    },
    "ace": {
      "matches": 10,
      "participants": 959
    }
  },
  "Cup_3": {
    "bronze": {
      "matches": 35,
      "participants": 3358
    },
    "silver": {
      "matches": 96,
      "participants": 9069
    },
    "gold": {
      "matches": 313,
      "participants": 29527
    },
    "platinum": {
      "matches": 10,
      "participants": 960
    },
    "diamond": {
      "matches": 16,
      "participants": 1538
    },
    "ace": {
      "matches": 45,
      "participants": 4280
    }
  },
  "Cup_4": {
    "bronze": {
      "matches": 2,
      "participants": 187
    },
    "silver": {
      "matches": 8,
      "participants": 742
    },
    "gold": {
      "matches": 37,
      "participants": 3416
    },
    "platinum": {
      "matches": 0,
      "participants": 0
    },
    "diamond": {
      "matches": 2,
      "participants": 196
    },
    "ace": {
      "matches": 3,
      "participants": 290
    }
  },
  "Cup_5": {
    "bronze": {
      "matches": 89,
      "participants": 1638
    }
  }
};

let cup_results = {};
Object.keys(cup_data).forEach(key => {
  let newCupKey = "Total_" + key;
  cup_results[newCupKey] = {};
  cup_results[newCupKey].matches = Object.values(cup_data[key]).reduce((acc, {
    matches
  }) => acc + matches, 0);
  cup_results[newCupKey].participants = Object.values(cup_data[key]).reduce((acc, {
    participants
  }) => acc + participants, 0);
});

console.log(cup_results);


1 commentaires

Merci pour votre contribution, c'est une autre fonction intéressante pour résoudre le problème!



2
votes

Vous pouvez, bien sûr, créer une fonction monolithique qui fera tout ce dont vous avez besoin, mais elle sera probablement plus facile à comprendre et à maintenir si vous la décomposez en idées plus petites.

Par exemple, vous pouvez créer une fonction qui ne prend qu'un objet et renvoie la somme des correspondances et participants . Ce sera court, lisible et, surtout, réutilisable:

let o = {"Cup_1": {"bronze": {"matches": 3,"participants": 289},"silver": {"matches": 20,"participants": 1874},"gold": {"matches": 35,"participants": 3227},"platinum": {"matches": 3,"participants": 294},"diamond": {"matches": 5,"participants": 482},"ace": {"matches": 6,"participants": 574}},"Cup_2": {"bronze": {"matches": 17,"participants": 1609},"silver": {"matches": 46,"participants": 4408},"gold": {"matches": 157,"participants": 14391},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 5,"participants": 469},"ace": {"matches": 10,"participants": 959}},"Cup_3": {"bronze": {"matches": 35,"participants": 3358},"silver": {"matches": 96,"participants": 9069},"gold": {"matches": 313,"participants": 29527},"platinum": {"matches": 10,"participants": 960},"diamond": {"matches": 16,"participants": 1538},"ace": {"matches": 45,"participants": 4280}},"Cup_4": {"bronze": {"matches": 2,"participants": 187},"silver": {"matches": 8,"participants": 742},"gold": {"matches": 37,"participants": 3416},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 2,"participants": 196},"ace": {"matches": 3,"participants": 290}},"Cup_5": {"bronze": {"matches": 89,"participants": 1638}}}

/* 
 * Base function. Sum an object's matches & participants
 */
function sumObj(obj){
  return Object.values(obj).reduce((sums, o) => {
    sums.matches += o.matches
    sums.participants += o.participants
    return sums
  }, {matches: 0, participants: 0})
}

let sums = Object.entries(o).reduce((totals, [key, val]) => {
  totals[key] = sumObj(val) // call the sum function for each value
  return totals
}, {})
console.log(sums)

/* 
 * Pass sums back into the same function to get a grand total: 
 */
console.log("grand total: ", sumObj(sums))

/* 
 * To sum only a subset filter the obj entries first:
 * Without Cup_5 
 */
let minus_5 = Object.entries(o)
  .filter(([k, v ]) => k != 'Cup_5')  // filter first
  .reduce((totals, [key, val]) => {
      totals[key] = sumObj(val)       // call the sum function for each value
      return totals
}, {})
console.log("all but Cup_5", minus_5)

/* 
 * To get only a subcategory, use map and make a new
 * array and pass it to the function:
 * Only bronze:
 */ 
let bronze = Object.values(o).map(item => item.bronze)  // get only bronze
console.log("Bronze", sumObj(bronze))

Vous pouvez maintenant utiliser et réutiliser cette fonction de différentes manières. Par exemple, pour obtenir toutes les catégories principales de l'objet plus grand, il suffit de réduire les valeurs et de définir une nouvelle clé pour chaque objet:

function sumObj(obj){
  // returns the sum of matches and participant propertes of all obj's values
  return Object.values(obj).reduce((sums, o) => {
    sums.matches += o.matches
    sums.participants += o.participants
    return sums
  }, {matches: 0, participants: 0})
}

Comme vous devriez le voir, c'est très flexible et vous permettra de créer de nombreux rapports différents avec la même fonction principale.


3 commentaires

Une manière intéressante de résoudre aussi, j'ai mentionné plus tôt que j'avais lu que cela pouvait être fait en utilisant .map et .reduce mais je n'avais jamais utilisé cette méthode auparavant, et je ne savais pas comment ça a marché. Merci pour votre contribution, je vais essayer d'apprendre à écrire ça aussi. Il semble plus facile de le diviser en fonctions plus petites.


Bonne chance @RogerHN, comme vous pouvez le voir dans les réponses, il existe de nombreuses façons d'atteindre le même objectif.


Ouais, c'est pourquoi j'aime poser des questions ici, les gens montrent toujours de nombreuses façons de le faire! J'en apprends plus tous les jours!



2
votes

Je pense que la fonction ci-dessous devrait être une solution générique à votre problème.

const data = {"Cup_1": {"bronze": {"matches": 3,"participants": 289},"silver": {"matches": 20,"participants": 1874},"gold": {"matches": 35,"participants": 3227},"platinum": {"matches": 3,"participants": 294},"diamond": {"matches": 5,"participants": 482},"ace": {"matches": 6,"participants": 574}},"Cup_2": {"bronze": {"matches": 17,"participants": 1609},"silver": {"matches": 46,"participants": 4408},"gold": {"matches": 157,"participants": 14391},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 5,"participants": 469},"ace": {"matches": 10,"participants": 959}},"Cup_3": {"bronze": {"matches": 35,"participants": 3358},"silver": {"matches": 96,"participants": 9069},"gold": {"matches": 313,"participants": 29527},"platinum": {"matches": 10,"participants": 960},"diamond": {"matches": 16,"participants": 1538},"ace": {"matches": 45,"participants": 4280}},"Cup_4": {"bronze": {"matches": 2,"participants": 187},"silver": {"matches": 8,"participants": 742},"gold": {"matches": 37,"participants": 3416},"platinum": {"matches": 0,"participants": 0},"diamond": {"matches": 2,"participants": 196},"ace": {"matches": 3,"participants": 290}},"Cup_5": {"bronze": {"matches": 89,"participants": 1638}}};

function getCumlativeData(data) {
  return Object.keys(data).reduce((cumData, cup)=>{
    let cupCumlative = {matches: 0, participants:0};
     Object.keys(data[cup]).forEach(med => {
       cumData[`Total_${med}`] = cumData[`Total_${med}`] || {matches: 0, participants:0};
       cumData[`Total_${med}`] = {
         matches: cumData[`Total_${med}`].matches + data[cup][med].matches,
         participants: cumData[`Total_${med}`].participants + data[cup][med].participants,
       };
       cupCumlative = {
          matches: cupCumlative.matches +  data[cup][med].matches,
          participants: cupCumlative.participants +  data[cup][med].participants
       };
     });
     return {...cumData, [`Total_${cup}`]: cupCumlative};
  },{});
}

console.log(getCumlativeData(data));


0 commentaires