简体   繁体   English

Javascript,使用reduce数组方法

[英]Javascript, using the reduce array method

So I'm doing the Odin Project.所以我正在做奥丁项目。 And one of the exercises is now hinting on using a reduce method.其中一个练习现在暗示使用 reduce 方法。 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.也许我必须解释测试用例,第一个是根据 yearBirth 和 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.我认为这与解决方案试图访问我要返回的 object 的 name 属性有关。 Because this is their hint:因为这是他们的提示:

  • You should return the whole person object, but the tests mostly just check to make sure the name is correct.您应该返回整个人 object,但测试大多只是检查以确保名称正确。

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有可能没有yearOfDeath (如果该人没有死)在这种情况下,您的代码将检索undefinedundefined - yearOfBirth会给您NaN

Any comparison with NaN will be false hence you won't go in your if branch, neither in your else if branch.NaN的任何比较都是false的,因此您不会在if分支中使用 go ,在else if分支中也不会。 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.如果你用一个简单的else替换else if你会返回一些东西,但它可能是一个错误的结果,因为比较是错误的。

That's why they made a function to retrieve the current year if there no yearOfDeath .这就是为什么如果没有yearOfDeath ,他们制作了 function 来检索当前年份。

Also you need to return the oldestPerson variable at the end of your function.您还需要在 function 的末尾返回oldestPerson变量。

In your code you can add something like (person.yearOfDeath || currentYear) :在您的代码中,您可以添加类似(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 -我注意到的几件事——

  • Use const (instead of let ) when we do not plan to reassign the variable当我们不打算重新分配变量时使用const (而不是let
  • Use an initial value (second argument) to reduce to prevent program from blowing up when the data set is empty使用初始值(第二个参数) reduce数据集为空时防止程序炸毁
  • Use of a compound result in reduce prevents us from recalculating the age of the oldest person in each iterationreduce中使用复合结果可以防止我们在每次迭代中重新计算oldest的人的年龄
  • Use of default values prevents null checks, unnecessary variable reassignments, and avoids running into NaN .使用默认值可防止 null 检查、不必要的变量重新分配,并避免遇到NaN Defaults also signal to programmer what type of data the function accepts默认值还向程序员表明 function 接受什么类型的数据

 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.是一样的,但是我只是在 function 的末尾添加了 return oldPerson。 Tell me if it works告诉我它是否有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM