简体   繁体   English

JavaScript数组reduce可以计算最小值,最大值和平均值的对象值

[英]JavaScript array reduce to calculate Object values of min, max, and avg

I've been stuck on this for a while. 我已经坚持了一段时间。 Thanks for any help! 谢谢你的帮助!

I have these two JavaScript (es6) arrays: 我有以下两个JavaScript(es6)数组:

const examListArray = [
  {examId: 'eee1', examName: 'Qtr 1 Exam'},
  {examId: 'eee2', examName: 'Qtr 2 Exam'},
  {examId: 'eee3', examName: 'Qtr 3 Exam'},
  {examId: 'eee4', examName: 'Final Exam'},
]

const examScoresArray = [

  {resultId: 'rrr01', examId: 'eee1', studentId: 'sss1', grade: 78},
  {resultId: 'rrr02', examId: 'eee1', studentId: 'sss2', grade: 82},
  {resultId: 'rrr03', examId: 'eee1', studentId: 'sss3', grade: 93},
  {resultId: 'rrr04', examId: 'eee1', studentId: 'sss4', grade: 85},
  {resultId: 'rrr05', examId: 'eee1', studentId: 'sss5', grade: 78},
  {resultId: 'rrr06', examId: 'eee1', studentId: 'sss6', grade: 84},
  {resultId: 'rrr07', examId: 'eee2', studentId: 'sss1', grade: 89},
  {resultId: 'rrr08', examId: 'eee2', studentId: 'sss2', grade: 88},
  {resultId: 'rrr09', examId: 'eee2', studentId: 'sss3', grade: 81},
  {resultId: 'rrr10', examId: 'eee2', studentId: 'sss4', grade: 95},

]

Here's the reduce function that I have so far, but need help with the Min, Max, and Avg parts, the examCount works perfectly. 这是我到目前为止拥有的reduce函数,但是在Min,Max和Avg零件方面需要帮助,examCount可以完美地工作。

const reducedExams = (list, scores) => {

  const countReducer = (scores, currentId) => {
    const countNum = scores.reduce((result, current) => {
      const foundAMatch = currentId === current.examId

      if (foundAMatch) {
        result++;
      }
      return result;
    }, 0);

    return countNum
  }

  const minScoreReducer = (scores, currentId) => {
     /*Need Help Here Please!*/
  }

  const maxScoreReducer = (scores, currentId) => {
     /*Need Help Here Please!*/
  }

  const avgScoreReducer = (scores, currentId) => {
     /*Need Help Here Please!*/
  }

  const resultData = list.reduce((result, current) => {

    const currentId = current.examId

    const examCount = countReducer(scores, currentId)
    const minScore = minScoreReducer(scores, currentId)
    const maxScore = maxScoreReducer(scores, currentId)
    const avgScore = avgScoreReducer(scores, currentId)

    return {
      ...result,
      [current.examName]: {
        ...result[current],
        examCount,
        minScore,
        maxScore,
        avgScore,

      }
    }

  }, {})

  return resultData

}

const examListTable = reducedExams(examListArray, examScoresArray)

console.log('exam table output', examListTable)

What I'm trying to do is is loop through my Exams List and make a table that will show something like this. 我想做的是遍历我的考试清单,并制作一张显示这样的表格。

_____________Count____Min____Max___Avg _____________计数____最小____最大___平均

Qtr 1 Exam:____6______78_____93___83.333 第一季度考试:____ 6 ______ 78 _____ 93 ___ 83.333

Qtr 2 Exam:____4______81_____95___88.25 第二季度考试:____ 4 ______ 81 _____ 95 ___ 88.25

Qtr 3 Exam:____0______0_____0_____0 第三季度考试:____ 0______0_____0_____0

Final Exam:____0______0_____0_____0 期末考试:____ 0______0_____0_____0

Any help would be greatly appreciated! 任何帮助将不胜感激!

And one last thing... if I'm going about this all wrong, ie, unnecessarily using reduce instead of some type of loop, Please by all means, I'm open to any suggestions. 还有最后一件事...如果我要解决所有这些错误,即不必要地使用reduce而不是某种类型的循环,请务必采取任何措施。 This feels very messy. 感觉很乱。

My stack: React, Redux, Firebase/FireStore 我的堆栈:React,Redux,Firebase / FireStore

I always upvote! 我总是投票! btw Thanks again! 顺便说一句再次感谢!

The trick to solving these problems is breaking them down into smaller objectives. 解决这些问题的技巧是将它们分解为较小的目标。

The first objective being to categorise scores by exam and the second being to derive metrics. 第一个目标是按考试对分数进行分类,第二个目标是得出指标。

Arrays can typically be categorised into object form using reduce() . 通常可以使用reduce()数组分类为对象形式。

Math is often useful for simple processes such as finding min / max values. Math通常对于简单的过程很有用,例如查找min / max

See below for a practical example. 请参见下面的实际示例。

 // Input. const exams = [{examId: 'eee1', examName: 'Qtr 1 Exam'},{examId: 'eee2', examName: 'Qtr 2 Exam'},{examId: 'eee3', examName: 'Qtr 3 Exam'},{examId: 'eee4', examName: 'Final Exam'}] const scores = [{resultId: 'rrr01', examId: 'eee1', studentId: 'sss1', grade: 78},{resultId: 'rrr02', examId: 'eee1', studentId: 'sss2', grade: 82},{resultId: 'rrr03', examId: 'eee1', studentId: 'sss3', grade: 93},{resultId: 'rrr04', examId: 'eee1', studentId: 'sss4', grade: 85},{resultId: 'rrr05', examId: 'eee1', studentId: 'sss5', grade: 78},{resultId: 'rrr06', examId: 'eee1', studentId: 'sss6', grade: 84},{resultId: 'rrr07', examId: 'eee2', studentId: 'sss1', grade: 89},{resultId: 'rrr08', examId: 'eee2', studentId: 'sss2', grade: 88},{resultId: 'rrr09', examId: 'eee2', studentId: 'sss3', grade: 81},{resultId: 'rrr10', examId: 'eee2', studentId: 'sss4', grade: 95}] // Math.Average. Math.average = (...args) => (args.reduce((total, x) => total + x, 0) / args.length) // Categorise. const categorise = scores => scores.reduce((output, score) => { const {examId: id, grade} = score if (output[id]) output[id].push(grade) else output[id] = [grade] return output }, {}) // Metrics. const getMetrics = (exams, scores) => exams.map(exam => { const {examId: id, examName: name} = exam const s = scores[id] || [] const isEmpty = !s.length return { name, count: s.length, min: isEmpty ? 0 : Math.min(...s), max: isEmpty ? 0 : Math.max(...s), average: isEmpty ? 0 : Math.average(...s) } }) // Output + Proof. const categorisedScores = categorise(scores) const metrics = getMetrics(exams, categorisedScores) console.log(metrics) 

You can use the array method filter to get the target you want and process. 您可以使用数组方法filter来获取所需的目标并进行处理。

const reducedExams = (list, scores) => {

  const countReducer = (scores, currentId) => {
    const matchedScores = scores.filter(score => score.examId === currentId);
    return matchedScores.length;
  }

  const minScoreReducer = (scores, currentId) => {
    const count = scores.filter(score => score.examId === currentId)
                        .reduce((min, score) => {
                          return score.grade < min ? score.grade : min;
                        }, Number.MAX_VALUE);
    if (count === Number.MAX_VALUE) {
      return 0;
    }
    return count;
  }

  const maxScoreReducer = (scores, currentId) => {
    const count = scores.filter(score => score.examId === currentId)
                        .reduce((max, score) => {
                          return score.grade > max ? score.grade : max;
                        }, Number.MIN_VALUE);
    if (count === Number.MIN_VALUE) {
      return 0;
    }
    return count;
  }

  const avgScoreReducer = (scores, currentId) => {
    let num = 0;
    const total = scores.filter(score => score.examId === currentId)
                      .reduce((sum, score) => {
                        num++;
                        sum += score.grade;
                        return sum;
                      }, 0);
    if (num === 0) {
      return 0;
    }

    return total / num;
  }

  const resultData = list.reduce((result, current) => {

    const currentId = current.examId
    const examCount = countReducer(scores, currentId)
    const minScore = minScoreReducer(scores, currentId)
    const maxScore = maxScoreReducer(scores, currentId)
    const avgScore = avgScoreReducer(scores, currentId)

    return {
      ...result,
      [current.examName]: {
        ...result[current],
        examCount,
        minScore,
        maxScore,
        avgScore,

      }
    }

  }, {})

  return resultData;

}

const examListTable = reducedExams(examListArray, examScoresArray)

console.log('exam table output', examListTable)

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

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