Javascript 如何获取此数组中最年长的人

Javascript 如何获取此数组中最年长的人,javascript,arrays,Javascript,Arrays,我在练习javascript,遇到了以下数组 const people = [ { name: 'Carly', yearOfBirth: 2018, }, { name: 'Ray', yearOfBirth: 1962, yearOfDeath: 2011 }, { name: 'Jane', yearOfBirth: 1912, yearOfDeath: 1941 }, ] 我试图找到数组中最年长的人

我在练习javascript,遇到了以下数组

const people = [
  {
    name: 'Carly',
    yearOfBirth: 2018,
  },
  {
    name: 'Ray',
    yearOfBirth: 1962,
    yearOfDeath: 2011
  },
  {
    name: 'Jane',
    yearOfBirth: 1912,
    yearOfDeath: 1941
  },
]
我试图找到数组中最年长的人,但我一直找错人。这是我的代码

  let findTheOldest = function(people) {
    const oldest = people.sort((a,b) => (a.yearOfDeath - a.yearOfBirth) > (b.yearOfDeath - b.yearOfBirth) ? -1 : 1);
    return oldest[0];
   }
所以它一直说卡莉是最年长的人而不是雷?我该怎么做呢?请注意,“Carly”没有死亡年份,因此她仍然活着。

您可以使用,对于没有死亡日期的人,可以使用当前年份:

const people=[{name:“Carly”,出生年份:2018},{name:“Ray”,出生年份:1962,死亡年份:2011},{name:“Jane”,出生年份:1912,死亡年份:1941}];
const findTheOldest=函数(人){
const thiswear=新日期().getFullYear();
返回人员。减少((res,person)=>{
const age=(person.yearOfDeath | | this year)-person.yearOfBirth;
返回年龄>res.age?{person,age}:res;
},{个人:空,年龄:0});
}

console.log(查找最年长的(人));//Ray
要使用sort查找最老的,您需要包含一个默认值,为没有死亡年份的人指定当前年份。下面我在一个名为“age”的助手函数中实现了这一点

但是,如果您的唯一目的是查找最大值,那么使用sort可能效率低下,特别是当您处理大量数据时:根据其他答案,尝试使用reduce

const people=[
{
姓名:“卡莉”,
出生年份:2018年,
},
{
姓名:“雷”,
出生年份:1962年,
死亡年份:2011年,
},
{
姓名:“简”,
出生年份:1912年,
死亡年份:1941年,
},
];
让我们找到最老的=功能(人){
const age=(x)=>(x.死亡年| |新日期().getFullYear())-x.出生年;
const laster=人。排序((a,b)=>
年龄(a)>年龄(b)?-1:1
);
返回最早的[0];
};

console.log(查找最年长的(人))作为一名工程师,我在大学学习的大多数证明都假设了一些东西,然后我们计算出来,然后在证明的最后,数学会告诉你你的假设是否正确

我们假设我们有一个名为
getAge(person)
的函数,其签名如下

// 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
};
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;

};
基本上,如果这个人没有死亡年,那么他仍然活着,并且在写下这个答案的时候是2020年

我们有一个
getOldest(people)
,它的签名如下

// 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
};
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;

};
最坏情况下的时间复杂度为o(n)

为了举例说明,让我们对此进行基准测试

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.
let people=[]
让init=()=>{
设randomInteger=(最小,最大)=>{
//返回最小值和最大值之间的随机整数,在stackoverflow上找到此值
返回Math.floor(Math.random()*(max-min+1))+min;
}
对于(设i=0;i<10000000;i++){//10m人
让dateOfBirth=parseInt('19'+randomInteger(10,99));
设dateOfDeath=parseInt('20'+randomInteger(10,99));
让人={
姓名:`person_${i}`,
dateOfBirth,//与dateOfBirth相同:dateOfBirth,
dateOfDeath,//相同的逻辑
}
people.push(person);//将其添加到people
}
}
init();
开始=性能。现在();//以毫秒为单位的时间
最年长的(人);
end=performance.now();//得到最年长的人后的时间(毫秒)
console.log((end-start)*Math.pow(10,-3))//经过的时间大约为0.2秒。

如果没有记录死亡年份,在进行计算之前,您可能需要将当前年份替换到该字段中。如果没有死亡年份,您应该在计算中使用最古老的年份。因为它们仍然存在,请查看我提出的解决方案。我很想质疑任务的逻辑。。。我是说,死人有年龄吗?再说一次,谷歌经常告诉我们这是一个死人的100多岁生日,所以也许死亡也不能阻止你变老?嗯,只是一个想法。我不确定这是否能在一个1000万人的数据集上工作。我试过了,但没有成功work@AhmedI.Elsayed它可以在10m下正常工作,在我的笔记本电脑上需要0.2秒,而您的解决方案需要9秒。。。(快45倍)/您的瓶颈在于每次迭代计算当前年份两次。将它存储在一个变量中可以提供与我类似的性能。在JavaScript圈子中,使用
reduce
循环编写
被认为是正常的吗?@user253751这与使用
for
循环编写
一样正常(使用
for
循环可以做任何事情)。如果有人不熟悉
reduce
,他们当然可以使用
for
,如果这能让他们更容易理解代码的话。但是
for
循环增加了复杂性,并强制了可变性(您必须在每次迭代中变异一个变量以跟踪结果)。但是JS提供了
reduce
,它就是为了这个目的而做的:迭代一个数组,并从中得到一个结果。这是函数式编程,不变性。如果这个工具是为它设计的,为什么不使用它呢?是的,但是你只需要最大化它的价值。对所有其他文件进行排序效率很低。谢谢,这篇文章写得很好!我也在学工程学!6秒似乎有点高。第二次快还是第三次快?(因为JIT编译器)@SamuelOkoth很高兴我能help@user253751是的,我复制了数组,花了很多时间才完成copied@user253751编辑的结果是0.2秒,我相信是谁提醒了我