I'm practicing my javascript and I've come across the following array.
const people = [
{
name: 'Carly',
yearOfBirth: 2018,
},
{
name: 'Ray',
yearOfBirth: 1962,
yearOfDeath: 2011
},
{
name: 'Jane',
yearOfBirth: 1912,
yearOfDeath: 1941
},
]
i'm trying to find the oldest person in the array but I keep getting the wrong person.here's my code
let findTheOldest = function(people) {
const oldest = people.sort((a,b) => (a.yearOfDeath - a.yearOfBirth) > (b.yearOfDeath - b.yearOfBirth) ? -1 : 1);
return oldest[0];
}
so it keeps saying that 'Carly' is the oldest person rather than 'Ray'? How would I go about it? note that 'Carly' has no yearOfDeath and therefore she is still alive.
You can use reduce
, and use the current year for people without a death date:
const people = [{name:"Carly",yearOfBirth:2018},{name:"Ray",yearOfBirth:1962,yearOfDeath:2011},{name:"Jane",yearOfBirth:1912,yearOfDeath:1941}];
const findTheOldest = function(people) {
const thisYear = new Date().getFullYear();
return people.reduce((res, person) => {
const age = (person.yearOfDeath || thisYear) - person.yearOfBirth;
return age > res.age ? { person, age } : res;
}, { person: null, age: 0 }).person;
}
console.log(findTheOldest(people)); // Ray
As an Engineer, most proofs I study at college assume something and we work it out, then at the end of the proof, Maths will tell you if your assumption was right.
We'll assume we have a function called getAge(person)
that has a signature as follows.
// this performance improvement of storing the year was suggested by @blex
let currentYear = new Date().getFullYear();
let getAge = (person) => {
return (person.yearOfDeath ? person.yearOfDeath : currentYear) - person.yearOfBirth
};
Basically, if the person doesn't have a .yearOfDeath
, he's still alive and the current year 2020 at the time of writing this answer.
and we have a getOldest(people)
that has a signature as follows.
let getOldest = people => {
/** Keep in mind that people can be mutated and you
need to avoid this here
*/
// An assumption. It can be right or wrong.
let oldest_person = people[0];
// The first method (slice) returns a shallow copy
// the second one (splice) removes the oldest_person
// removing it makes the loop count decrease by one. Nothing else.
// we don't need a deep copy, we won't alter the people.
people = (people.slice()).splice(1);
// You could save the getAge(oldest_person) in a variable
// instead of computing it each time
// I wanted this to be as readable as possible.
for (let person of people){
if (getAge(person) > getAge(oldest_person)){
// Congrats! we have a new older person!
oldest_person = person;
}
}
return oldest_person;
};
This has a worst-case time complexity of o(n).
For illustration, let's benchmark this.
let people = []
let init = () => {
let randomInteger = (min, max) => {
// return random integer between min, max, found this on stackoverflow
return Math.floor(Math.random() * (max - min + 1)) + min;
}
for (let i = 0; i < 10000000; i++){ // 10m person
let dateOfBirth = parseInt('19' + randomInteger(10,99));
let dateOfDeath = parseInt('20' + randomInteger(10, 99));
let person = {
name: `person_${i}`,
dateOfBirth, // same as dateOfBirth: dateOfBirth,
dateOfDeath, // same logic
}
people.push(person); // add it to people
}
}
init();
start = performance.now(); // time in millisecs
getOldest(people);
end = performance.now(); // time in millisecs after getting the oldest person
console.log((end - start ) * Math.pow(10, -3)) // time elapsed is around 0.2 secs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With