0

I'm making a simple RPG and trying to calculate which attribute should be increased when a character levels up. They have a potential limit for each attribute and I want to increment the attribute that is furthest from its potential.

I can loop through each attribute and subtract its current value from its potential value to get the difference. I can then push the difference to an array. The result looks like:

[
{Strength: 5},
{Dexterity: 6},
{Constitution: 3},
{Wisdom: 4},
{Charisma: 8}
]

Charisma is the key with the highest difference, so how can I evaluate this and return the name of the key (not the value itself)?

EDIT: Here is the logic which is used to get the array:

let difference = [];
let key;
for (key in currentAttributes) {
  difference.push({[key]: potentialAttributes[key] - currentAttributes[key]});
};
DJ_Beardsquirt
  • 289
  • 5
  • 14
  • Can you please show the logic that you are using to generate that array? You're question eludes that you are doing that programatically – Taplar Oct 08 '19 at 15:00
  • `Math.max(...arr.map(e => e[Object.keys(e)[0]]));` – ASDFGerte Oct 08 '19 at 15:02
  • 2
    Using an array of objects makes this more cumbersome than it needs to be. The keys are likely all unique, so just use one object to stuff them into. If you do that, your answer is here: https://stackoverflow.com/q/27376295/476 – deceze Oct 08 '19 at 15:02
  • @ASDFGerte this returns the value, not the key. – DJ_Beardsquirt Oct 08 '19 at 15:13

3 Answers3

5

Simple reduce with Object.entries

const items = [
  { Strength: 5 },
  { Dexterity: 6 },
  { Constitution: 3 },
  { Wisdom: 4 },
  { Charisma: 8 }
]

const biggest = items.reduce((biggest, current, ind) => {
  const parts = Object.entries(current)[0]  //RETURNS [KEY, VALUE]
  return (!ind || parts[1] > biggest[1]) ? parts : biggest  // IF FIRST OR BIGGER
}, null) 
console.log(biggest[0])  // 0 = KEY, 1 = BIGGEST VALUE

Your data model is a bit weird with the array with objects, a better model would just be an object.

const items = {
  Strength: 5,
  Dexterity: 6,
  Constitution: 3,
  Wisdom: 4,
  Charisma: 8
}

const biggest = Object.entries(items)
  .reduce((biggest, current, ind) => {
    const parts = current
    return (!ind || parts[1] > biggest[1]) ? parts : biggest  
}, null) 

console.log(biggest[0])
epascarello
  • 204,599
  • 20
  • 195
  • 236
3

You could create an object, take the entries and reduce the entries by taking the entry with the greatest value. At the end take the key from the entry.

var data = [{ Strength: 5 }, { Dexterity: 6 }, { Constitution: 3 }, { Wisdom: 4 }, { Charisma: 8 }],
    greatest = Object
        .entries(Object.assign({}, ...data))
        .reduce((a, b) => a[1] > b[1] ? a : b)
        [0];

console.log(greatest);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

Sort in descending order and grab the first item:

let attributes = [
  {Strength: 5},
  {Dexterity: 6},
  {Constitution: 3},
  {Wisdom: 4},
  {Charisma: 8}
];

//for convenience
const getValue = obj => Object.values(obj)[0];

//sort descending
attributes.sort((a, b) => getValue(b) - getValue(a));

let highest = attributes[0];
console.log(Object.keys(highest)[0]);

Alternatively, go though the array and find the highest score:

let attributes = [
  {Strength: 5},
  {Dexterity: 6},
  {Constitution: 3},
  {Wisdom: 4},
  {Charisma: 8}
];

//for convenience
const getValue = obj => Object.values(obj)[0];

//find the highest score
let highest = attributes.reduce((currentHighest, nextItem) => getValue(currentHighest) > getValue(nextItem) ?  currentHighest : nextItem);

console.log(Object.keys(highest)[0]);
VLAZ
  • 26,331
  • 9
  • 49
  • 67