从 Javascript 数组派生计算数据

Derived Computed Data from Javascript Array

感谢您的帮助!我已经坚持了一段时间。

我有这个数组

students: [
  {studentId: 'sss1', isAthlete: true, isHonors: true, testScore: 78, studentName: 'Bobby'},
  {studentId: 'sss2', isAthlete: false, isHonors: false, testScore: 93, studentName: 'Sally'},
  {studentId: 'sss3', isAthlete: true, isHonors: true, testScore: 82, studentName: 'Mikey'}, 
  {studentId: 'sss4', isAthlete: false, isHonors: false, testScore: 88, studentName: 'Billy'}, 
  {studentId: 'sss5', isAthlete: true, isHonors: false, testScore: 91, studentName: 'Davey'}, 
  {studentId: 'sss6', isAthlete: false, isHonors: false, testScore: 94, studentName: 'Joey'}, 
  {studentId: 'sss7', isAthlete: false, isHonors: true, testScore: 97, studentName: 'Nancy'}, 
  {studentId: 'sss8', isAthlete: true, isHonors: false, testScore: 83, studentName: 'Susie'}, 
  {studentId: 'sss9', isAthlete: false, isHonors: false, testScore: 72, studentName: 'Jimmy'}, 

]

上面的数组是使用reselect计算出来的,然后完美地注入到我的React组件中。

现在,在我的 React 组件中,我需要向我的用户展示:

Total Student Count: 9
Total Athlete Count: 4
Total Honors Count: 3

Average Overall Score: 86.44
Average Honors Score: 85.67
Average Athlete Score: 83.5

Highest Overall Student: Nancy
Highest Honors Student: Nancy
Highest Athlete Student: Davey

我的问题
1. 什么是 "best practice" for where 做这个计算?
2. 谁能想出一个数组方法来有效地进行这个计算?我的实际阵列有数百名学生。

不想在这里成为一个吃白食的人,但发现自己写了几十个这样的东西:

const athCount = students.filter(s => s.isAthlete === true).length

并且有那种我做错了的刺痛感。

谢谢你

  1. Can anyone dream up an array method to efficiently make this calculation? My actual array has hundreds of students.

您需要迭代数组。没有别的办法。但是,您可能只这样做一次:

  let athletes = 0, honors = 0, honorScore = 0, athleteScore= 0, totalScore = 0, best = { score: 0 };
  for(const student of students){ 
   athletes += student.isAthlete;
   honors += student.isHonors;
   totalScore += student.score;
   /*...*/
   if(student.score > best.score)
      best = student;
 }
    const data = [
  {studentId: 'sss1', isAthlete: true, isHonors: true, testScore: 78, studentName: 'Bobby'},
  {studentId: 'sss2', isAthlete: false, isHonors: false, testScore: 93, studentName: 'Sally'},
  {studentId: 'sss3', isAthlete: true, isHonors: true, testScore: 82, studentName: 'Mikey'}, 
  {studentId: 'sss4', isAthlete: false, isHonors: false, testScore: 88, studentName: 'Billy'}, 
  {studentId: 'sss5', isAthlete: true, isHonors: false, testScore: 91, studentName: 'Davey'}, 
  {studentId: 'sss6', isAthlete: false, isHonors: false, testScore: 94, studentName: 'Joey'}, 
  {studentId: 'sss7', isAthlete: false, isHonors: true, testScore: 97, studentName: 'Nancy'}, 
  {studentId: 'sss8', isAthlete: true, isHonors: false, testScore: 83, studentName: 'Susie'}, 
  {studentId: 'sss9', isAthlete: false, isHonors: false, testScore: 72, studentName: 'Jimmy'}, 
]

const initialResult = {
  count : {
    athlete : 0,
    honors : 0,
    total : 0
  },
  accumulate : {
    athlete : 0,
    honors : 0,
    total : 0
  },
  best : {
    name : null,
    score : null
  }
};

const result = data.reduce(process, initialResult);


function process (result, record) {
  result.count.total++;
  result.accumulate.total += record.testScore;

  if (record.isAthlete) {
    result.count.athlete++;
    result.accumulate.athlete += record.testScore;
  }
  if (record.isHonors) {
    result.count.honors++;
    result.accumulate.honors += record.testScore;
  }



  let best = result.best;

  if (best.name === null && best.score === null) {
    best.name = record.studentName;
    best.score = record.testScore;
  } else {
    if (best.score < record.testScore) {
      best.name = record.studentName;
      best.score = record.testScore;
    }
  } 

  return result;
}

console.log(result);

答案1:在不知道输入数据变化频率的情况下,我认为你应该把所有的计算都放在render函数中。这样,DOM 始终与数据一致。在大多数情况下,这会工作得很好,您不会注意到任何性能影响。

答案 2:在这个例子中,_lodash package

const athletes = students.filter(({isAthlete}) => isAthlete);
const athleteCount = athletes.length;

const averageScore = _.sumBy(students, 'testScore') / students.length;
const averageHonorsScore = _.sumBy(athletes, 'testScore') / students.length;

const highestSCore = _.maxBy(students, 'testScore')
const highestAthleteScore = _.maxBy(athletes, 'testScore');