简体   繁体   中英

How can I compare values from multiple objects?

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 (ie 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!

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.

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);

Considering you have mentioned that not all skills are equally important, I would suggest weighted total as a cumulative metric:

Following demo implements that approach:

 //src array 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} ]; //cumulative score const cumulative = soldier => { //weight for each skill const weights = {shooting: 1, combat: 1.5, tactic: 1.8}; //extract skill properties into skills-object ({name, ...skills} = soldier); //iterate through skills and calculate weighted total return Object.entries(skills).reduce((score,item) => score += item[1]*weights[item[0]],0); }; //best performer const bestPerformer = soldiers.reduce((best, soldier) => cummulative(best) > cumulative(soldier) ? best : soldier, soldiers[0]); console.log(bestPerformer); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM