Reputation: 59
I tried to find the highest score on an object in this array, but the result is incorrect. Should we reset the score to be 0 again? I was trying to put the score variable below the obj[i.class]
but nothing changed:
function theScore (students) {
var obj = {};
score = 0;
for(i of students){
if(score < i.score) {
obj[i.class] = {
name: i.name,
score: i.score
};
};
};
return obj;
};
console.log(theScore([
{
name: 'Sara',
score: 90,
class: 'A'
},
{
name: 'Poyi',
score: 85,
class: 'B'
},
{
name: 'Adert',
score: 74,
class: 'A'
},
{
name: 'Shynta',
score: 78,
class: 'B'
}
]));
Desired output:
{
A: {
name: 'Sara',
score: 90
},
B: {
name: 'Poyi',
score: 85
}
}
Upvotes: 1
Views: 72
Reputation: 18515
The issue with your code was never actually comparing the the actual object score but to 0 always.
If you really want to use for in
loop for this you can do something like (with slight changes to your code):
var data = [ { name: 'Sara', score: 90, class: 'A' }, { name: 'Poyi', score: 85, class: 'B' }, { name: 'Adert', score: 74, class: 'A' }, { name: 'Shynta', score: 78, class: 'B' } ]
function theScore (students) {
var obj = {}
for(i of students){
if(!obj[i.class] || obj[i.class].score < i.score) {
obj[i.class] = {name: i.name, score: i.score}
}
}
return obj
}
console.log(theScore(data))
Or you can use reduce
and solve it like this:
var data = [ { name: 'Sara', score: 90, class: 'A' }, { name: 'Poyi', score: 85, class: 'B' }, { name: 'Adert', score: 74, class: 'A' }, { name: 'Shynta', score: 78, class: 'B' } ]
const maxByClass = (d) => d.reduce((r,{name, score, ...c}) => {
r[c.class] = r[c.class] ? r[c.class].score > score ? r[c.class] : {name, score} : {name, score}
return r
}, {})
console.log(maxByClass(data))
Since reduce returns an accumulator we simply need to assign the correct object prop based on which one of the 2 classes scores is larger and return.
Upvotes: 0
Reputation: 5303
The problem with your code is that you don't make any distinction between students' scores in one class versus another class. You also are not updating the score when you find a higher one, so every student's score (unless it's 0) will be higher than score
every time your loop runs, and you just end up with the last score in the list.
EDIT: edited to show how to do this with only one loop
You need to:
function theScore (students) {
const highScoresByClass = {};
const scores = {A: 0, B: 0, C: 0};
for (const student of students){
const classHighScore = scores[student.class];
if(classHighScore < student.score) {
scores[student.class] = student.score;
highScoresByClass[student.class] = {
name: student.name,
score: student.score
};
};
};
return highScoresByClass;
};
console.log(theScore([
{
name: 'Sara',
score: 90,
class: 'A'
},
{
name: 'Poyi',
score: 85,
class: 'B'
},
{
name: 'Adert',
score: 74,
class: 'A'
},
{
name: 'Shynta',
score: 78,
class: 'B'
}
]));
Upvotes: 0
Reputation: 33726
You need to track the already checked classes
.
A cleaner alternative is using the function Array.prototype.reduce
to build the desired output. As you can see, basically, this approach is keeping a track of the previously checked classes
.
function theScore (students) {
return students.reduce((a, c) => {
a[c.class] = (a[c.class] || (a[c.class] = c));
if (c.score > a[c.class].score) a[c.class] = c;
return a;
}, Object.create(null));
}
console.log(theScore([ { name: 'Sara', score: 90, class: 'A' }, { name: 'Poyi', score: 85, class: 'B' }, { name: 'Adert', score: 74, class: 'A' }, { name: 'Shynta', score: 78, class: 'B' }]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 620
The score is not being changed after you find the highest score. Change the score to the current score. Thanks. Instead of an object with map, use an object with index(Array). This should work.
function theScore (students) {
var obj = [];
score = 0;
for(i of students){
if(obj.length === 0) {
obj.push( i );
} else {
for( var x = 0; x < obj.length; x++ ){
if( i.score > obj[x].score ){
obj.splice( x, 0, i );
break;
}
}
if( x === obj.length ){
obj.push(i);
}
}
};
return obj;
};
console.log(theScore([
{
name: 'Sara',
score: 90,
class: 'A'
},
{
name: 'Poyi',
score: 85,
class: 'B'
},
{
name: 'Adert',
score: 74,
class: 'A'
},
{
name: 'Shynta',
score: 78,
class: 'B'
}
]));
Upvotes: 0
Reputation: 359
Can't you massively simplify your function's obj assignment?
function theScore (students) {
var obj = {};
var score = 0;
for(i of students){
if(i.score > score ) {
score = i.score; // Keep track of the highest-score-found-so-far
obj = i; // Keep track of the highest scoring object
}
}
return obj;
}
Upvotes: 1