#javascript #arrays #javascript-objects
Вопрос:
У меня есть сильное подозрение, что мой код слишком неуклюж и может быть написан более лаконично и эффективно. Цель состоит в том, чтобы сравнить массив объектов (представляющих игроков), чтобы найти игрока с самым высоким свойством majorityScore. Если несколько игроков имеют одинаковый высокий балл, затем сравните фракции соавторов с картой (приоритетная карта), чтобы определить, кто победит.
players = [
{
majorityScore: 4,
faction: 'AR'
},
{
majorityScore: 8,
faction: 'MOU'
},
{
majorityScore: 2,
faction: 'MOB'
},
{
majorityScore: 8,
faction: 'I'
}
];
const priorityMap = {
'MOB': 1,
'I': 2,
'MOU': 3,
'AR': 4,
'S' : 0
}
let winner;
let highScore = -1;
let duplicates = [];
for(let i = 0; i < players.length; i ){
if(players[i].majorityScore > highScore){
highScore = players[i].majorityScore;
winner = players[i]
duplicates = [winner];
} else if (players[i].majorityScore === highScore){
duplicates.push(players[i]);
};
}
if(duplicates.length > 1){
let highFactionScore = duplicates.reduce((a,v) => {
if(priorityMap[v.faction] > a){
a = priorityMap[v.faction];
}
return a;
}, 0);
let winningFaction = Object.keys(priorityMap).find((k) => {
return priorityMap[k] === highFactionScore;
});
winner = duplicates.filter((v) => {
return v.faction === winningFaction
})
}
Ответ №1:
Поскольку вы уменьшаете массив объектов в один объект, здесь можно использовать функцию уменьшения: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Вместо того, чтобы проверять фракции после получения игроков с наибольшим большинством голосов, вы можете проверять фракции всякий раз, когда в конечном итоге сравниваете игроков с одинаковым большинством голосов.
let winner = players.reduce((accum, currVal) => {
if (accum.majorityScore < currVal.majorityScore) {
return currVal;
} else if (accum.majorityScore > currVal.majorityScore) {
return accum;
} else {
return priorityMap[accum.faction] > priorityMap[currVal.faction] ? accum : currVal
}
});
Ответ №2:
Вот несколько более короткий метод. Он использует временный объект для ведения словаря, в котором баллы являются ключами. По мере повторения мы добавляем значение priorityMap[faction]
свойства score и изменяем его только в том случае, если значение больше, чем сохраненное.
const players=[{majorityScore:4,faction:"AR"},{majorityScore:8,faction:"MOU"},{majorityScore:8,faction:"MOU12"},{majorityScore:8,faction:"MOU20"},{majorityScore:2,faction:"MOB"},{majorityScore:2,faction:"MOB2"},{majorityScore:8,faction:"I"}],priorityMap={MOB:1,I:2,MOU:3,MOB2:4,AR:4,S:0,MOU12:21,MOU20:22};
function getGroups(arr) {
// Create the temp object
// We'll be using the scores as keys, and using
// the value in priorityMap as the value
// As we iterate we check the new priorityMap value
// against the old one
const temp = {};
// Iterate over the players array
return arr.reduce((acc, c) => {
const { majorityScore: score, faction } = c;
// If the accumulator object doesn't have a key that
// matches the score, add a new object
acc[score] = (acc[score] || { majorityScore: score, faction });
// If the new value of priorityMap[faction] is
// greater than the one stored in temp
// update the faction in the accumulator for that score
if (priorityMap[faction] > temp[score]) {
acc[score].faction = faction;
}
// Update the temp object with the
// priorityMap[faction] value
temp[score] = priorityMap[faction];
// Return the accumulator for the next iteration
return acc;
}, {});
}
console.log(getGroups(players));