0

I want to compare values from objects that I keep in an array.

I know that I can create new arrays with values from each object but I'm trying to find some way to do it without creating them.

Consider we have such situation:

soldiers[first, second, third]
first{name: John, shooting: 95, combat: 50, tactic: 88}
second{name: Arnold, shooting: 97, combat: 72, tactic: 68}
third{name: William, shooting: 87, combat: 86, tactic: 97}

I'd like to select the best soldier from the provided above - but I can't create one rating (i.e. average).

There will be some conditions that soldier must fill - for example: at least 60 points in combat (no matter if every other property is 100).

So I'm trying to find way to compare multiple properties and return name of just one soldier.

I'll appreciate every tip. Thanks!

Vontar
  • 64
  • 4
  • You need isolate the problem and debug from there. If you're stuck provide a clear explanation of what isn't working with a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). I suggest reading [How to Ask a good question](https://stackoverflow.com/help/how-to-ask). Also, be sure to [take the tour](https://stackoverflow.com/tour) – André DS Apr 19 '19 at 12:03
  • Possible duplicate of [How to find first element of array matching a boolean condition in JavaScript?](https://stackoverflow.com/questions/10457264/how-to-find-first-element-of-array-matching-a-boolean-condition-in-javascript) – adiga Apr 19 '19 at 12:06
  • `soldiers.find(s => s.combat > 60 && s.shooting > 90)` – adiga Apr 19 '19 at 12:08
  • Thank your very much! Using your anwer I found out that I can use .map() and .filter() methods but I just need to use proper naming. – Vontar Apr 19 '19 at 12:18
  • @PiotrKaczmarek : Assuming, you have mentioned that not all skills are equally important while calculating the best performer, total or average score does not fulfill that requirement. Weighted total would suit the purpose much better. So, if you're still interested in such approach, you may check out my answer below. – Yevhen Horbunkov Apr 19 '19 at 13:20

2 Answers2

0

I have made you an exmaple with comments. Let me know if this pushes you in the right direction or if you need any other help.

const soldiers = [{
    name: "John",
    shooting: 95,
    combat: 50,
    tactic: 88
  },
  {
    name: "Arnold",
    shooting: 97,
    combat: 72,
    tactic: 68
  },
  {
    name: "William",
    shooting: 87,
    combat: 86,
    tactic: 97
  }
];

const filteredSoldiers = soldiers
  .filter(soldier => soldier.combat > 60) // Find every soldier where combat is higher than 60
  .map(soldier => {
    return {
      name: soldier.name,
      average: (soldier.combat + soldier.tactic + soldier.shooting) / 3
    };
    // map will return an array with the filtered soldiers, and we put their average and their name in there
  })
  .sort((a, b) => b.average - a.average);
// Lastly we sort them high to low by their average score

console.log(
  filteredSoldiers.length > 0 ? filteredSoldiers[0].name : 'No soldiers with combat score higher thn 60'
);

jsfiddle

In the filter condition you can of course add more checks.

adiga
  • 34,372
  • 9
  • 61
  • 83
Tim VN
  • 1,183
  • 1
  • 7
  • 19
  • Thank you so much! That was exactly what I was looking for - reading about find() method - mentioned above - I realised that I can solve my problem with filter(). I was afraid of using filter() for array with objects but it worked perfect for me. Thank you again. – Vontar Apr 19 '19 at 12:26
  • [How do I create a runnable Stack snippet?](https://meta.stackoverflow.com/questions/358992) – adiga Apr 19 '19 at 12:27
0

You need to got through all items and select best value;

Note that some soldiers can have similar values, that's why values.name is array

let a = {
    name: "John", shooting: 95, combat: 50, tactic: 88
};
let b = {
    name: "Arnold", shooting: 97, combat: 72, tactic: 68
};
let c = {
    name: "William", shooting: 87, combat: 86, tactic: 97
};
let soldiers = [a, b, c];
let values = {
    shooting: {
        name: [],
        score: 0
    },
    combat: {
        name: [],
        score: 0
    },
    tactic: {
        name: [],
        score: 0
    }
};

soldiers.map((item) => {
    ['shooting', 'combat', 'tactic'].forEach(name => {
        if (item[name] > values[name].score) {
            values[name].name = [item.name];
            values[name].score = item[name];
        } else if (item[name] === values[name].score) {
            values[name].name.push(item.name);
        }
    });
});

console.log(values);
Ivan Ivanov
  • 2,076
  • 16
  • 33