So I'm doing the Odin Project. And one of the exercises is now hinting on using a reduce method. I am kind of stuck here and I've already looked at the solution. However I don't really know what kind of error I'm making if I do it on my own. The code that I've got is this:
let findTheOldest = function(people) {
const oldestPerson = people.reduce((winner, person) => {
if ((person.yearOfDeath - person.yearOfBirth) > (winner.yearOfDeath - winner.yearOfBirth)) {
return person;
} else if ((person.yearOfDeath - person.yearOfBirth) <= (winner.yearOfDeath - winner.yearOfBirth)) {
return winner;
}
});
}
And the code they have is:
const findTheOldest = function(array) {
return array.reduce((oldest, currentPerson) => {
const oldestAge = getAge(oldest.yearOfBirth, oldest.yearOfDeath)
const currentAge = getAge(currentPerson.yearOfBirth, currentPerson.yearOfDeath)
return oldestAge < currentAge ? currentPerson : oldest
})
}
const getAge = function(birth, death) {
if (!death) {
death = new Date().getFullYear();
}
return death - birth;
}
Now, I know if I look at it that their code is a lot more structured. But my own "solution" is the closest one I came to. And by now I'm trying to figure out what the difference is. I know that their code is eventually better. It's a lot more tidy, and using separate variables for storing the age is a lot cleaner and more clear. However both me and them return the "objects" in the same way. And for the first test case I should be able to pass, is what I'm thinking right now.
Maybe I must explain the test cases, the first one finds the oldest person based on calculating their age from yearBirth and yearDeath. And then the second test case should account for a person still being alive. And the third test case is that the alive person is in fact the oldest one so it should return that one. I'm only trying for the first one at the moment.
The error I'm getting is that "Cannot read property 'name' of undefined". I think that has got to do with the fact that the solution is trying to access the name property of the object I'm returning. Because this is their hint:
There is a possibility that there is no yearOfDeath
(if the person is not dead) in that case your code will retrieve undefined
and undefined - yearOfBirth
will give you NaN
Any comparison with NaN
will be false
hence you won't go in your if
branch, neither in your else if
branch. Therefore you won't return anything. If you replace the else if
with a simple else
you would return something but it would probably be a wrong result since the comparison is wrong.
That's why they made a function to retrieve the current year if there no yearOfDeath
.
Also you need to return the oldestPerson
variable at the end of your function.
In your code you can add something like (person.yearOfDeath || currentYear)
:
let findTheOldest = function(people) { const currentYear = new Date().getFullYear(); const oldestPerson = people.reduce((winner, person) => { if (((person.yearOfDeath || currentYear) - person.yearOfBirth) > ((winner.yearOfDeath || currentYear) - winner.yearOfBirth)) { return person; } else if (((person.yearOfDeath || currentYear) - person.yearOfBirth) <= ((winner.yearOfDeath || currentYear) - winner.yearOfBirth)) { return winner; } }); return oldestPerson; } const p1 = { yearOfBirth: 1990, yearOfDeath: 2015 } const p2 = { yearOfBirth: 1990 } // Edge case: calculate his age with current year console.log(findTheOldest([p1, p2]))
Now this code is quit difficult to read, that's why it's good to split it into separate functions.
A few things I noticed -
const
(instead of let
) when we do not plan to reassign the variablereduce
to prevent program from blowing up when the data set is emptyreduce
prevents us from recalculating the age of the oldest
person in each iterationNaN
. Defaults also signal to programmer what type of data the function accepts const findTheOldest = (people = []) => people.reduce ( ([ oldest, oldestAge ], person) => { const age = getAge(person) // only compute age of current person return age > oldestAge? [ person, age ]: [ oldest, oldestAge ] }, [ undefined, -Infinity ] // initial value ) [0] // reduce returns [ <person>, <age> ], [0] gets the person out const getAge = ({ yearOfBirth = 0, yearOfDeath = 0 }) => yearOfDeath? yearOfDeath - yearOfBirth: (new Date).getFullYear() - yearOfBirth const peeps = [ { name: "Alice", yearOfBirth: 2000 }, { name: "Gertrude", yearOfBirth: 1910 }, { name: "Martha", yearOfBirth: 1900, yearOfDeath: 2006 }, { name: "Wanda", yearOfBirth: 1940 } ] // works as expected console.log(findTheOldest(peeps)) // { name: "Gertrude", ... } // works when data source is empty console.log(findTheOldest([])) // undefined // works when data is missing. console.log(findTheOldest()) // undefined
Try with this:
let findTheOldest = function(people) { const oldestPerson = people.reduce((winner, person) => { if ((person.yearOfDeath - person.yearOfBirth) > (winner.yearOfDeath - winner.yearOfBirth)) { return person; } else if ((person.yearOfDeath - person.yearOfBirth) <= (winner.yearOfDeath - winner.yearOfBirth)) { return winner; } }); return oldestPerson; }
It is the same, but I just added return oldestPerson at the end of the function. Tell me if it works
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.