【问题标题】:Assign the same rank to student with the same scores为相同分数的学生分配相同的排名
【发布时间】:2021-07-30 12:41:09
【问题描述】:

我正在根据学生的分数为他们分配排名,但我遇到了一个问题,即如果两个或更多学生的分数相同,他们将获得不同的排名。

E.G John、Rita 和 Mary 获得 76 分。John 排名第一,Rita 排名第二,Mary 排名第三。

  1. 约翰 ==> 76
  2. 丽塔 ==> 76
  3. 玛丽 ==> 76
  4. Bukky ==>74

我希望他们三个排名第一。

  1. 约翰 ==> 76
  2. 丽塔 ==> 76
  3. 玛丽 ==> 76
  4. Bukky ==>74
public function getStudentpositionOnlyClass($student_id, $class_id, $terms)
{
    $array_product = array();

    if ($class_id == 22 || $class_id == 23) {
        if ($terms == 'f') {
            $totField = 'ft_tot_score';
            $table = 'ftscores_rn';
        } elseif ($terms == 'm') {
            $totField = 'mt_tot_score';
            $table = 'mtscores_rn';
        } elseif ($terms == 's') {
            $totField = 'tot_score';
            $table = 'scores_rn';
        } elseif ($terms == 'h') {
            $totField = 'h_tot_score';
            $table = 'hscores_rn';
        }
    } else {
        if ($terms == 'f') {
            $totField = 'ft_tot_score';
            $table = 'ftscores_primary';
        } elseif ($terms == 'm') {
            $totField = 'mt_tot_score';
            $table = 'mtscores_primary';
        } elseif ($terms == 's') {
            $totField = 'tot_score';
            $table = 'scores_primary';
        } elseif ($terms == 'h') {
            $totField = 'h_tot_score';
            $table = 'hscores_primary';
        }
    }

    $fail = 0;
    $pass = 0;

    $resultlist = $this->student_model->fullSearchByClass($class_id);

    foreach ($resultlist->result_array() as $key => $stdName) {
        $idd = $key + 1;
        $mId[$idd] = $stdName['pstudent_id'];

        $totalSubMarks = $this->db->query(
            "SELECT  mts.subject_id
                     FROM " . $table . " mts
                     LEFT JOIN subjects sub ON(sub.id=mts.subject_id)
                     WHERE class_id=" . $class_id .
            " AND mts.subject_id IS NOT NULL
                     GROUP BY mts.subject_id ORDER BY sub.name");
        $gtotal = 0;
        $totSubjects = 0;

        foreach ($totalSubMarks->result_array() as $tmrow) {

            $totalMarks = $this->student_model->getTotalMarksForStudnets($tmrow['subject_id'],
                $stdName['pstudent_id'], $table, $totField);
            // //// set mtotalmark

            $gtotal = $gtotal + $totalMarks;
            // //// set mgtotal
            $mGTotal[$idd] = $gtotal;

            if ($totalMarks != 0) {
                $totSubjects = $totSubjects + 1;
            }
            // //// set mAvg
            if ($totSubjects != 0) {
                $mAvg[$idd] = round($gtotal / $totSubjects, 1);
            } else {
                $mAvg[$idd] = 0;
            }
        }

        // /////////
        if ($totSubjects != 0) {
            $percentage = ($gtotal / $totSubjects);
        }
        if ($percentage >= 0 && $percentage <= 39.99) {
            $fail = $fail + 1;
        } else {
            $pass = $pass + 1;
        }
    }

    foreach ($mAvg as $dd => $val) {
        // if pure numbers store in nums array
        if (! is_nan($val)) {
            $nums[$dd] = $val;
        }
    }
    arsort($nums);

    $id = 1;
    foreach ($nums as $kk => $av) {

        foreach ($totalSubMarks->result_array() as $tmrow) {
            $totalMarks = $this->student_model->getTotalMarksForStudnets($tmrow['subject_id'], $mId[$kk], $table,
                $totField);
        }

        if ($student_id == $mId[$kk]) {
            return $id;
        }
        // $array_product['student'.$mId[$kk]]= $id;
        $id += 1;
    }
}

【问题讨论】:

  • 更像 1,1,1,2。
  • 您没有在query() 通话中使用占位符。
  • 嗯,“密集等级”。这是一个很好的阅读:mattmazur.com/2017/03/26/exploring-ranking-techniques-in-mysql
  • 对调用数据库的模型方法的迭代调用是个坏主意。
  • 我在看控制器方法吗? $totSubjects = $totSubjects + 1; 更简单地表示为++$totSubjects;

标签: php codeigniter


【解决方案1】:

正如 mickmackusa 在他的评论中所说,您必须记住以前的分数,并且只有在分数发生变化时才增加排名。由于您已经订购了结果,我们可以假设 2 次迭代之间的分数变化总是减少。

您的变量名称​​非常不直观。所以也许我的代码更改在错误的地方,但你应该理解这个概念。我假设$totSubjects 就是那个分数。

尽量不要过多地缩短变量的名称,因为您没有好处,但会丢失关于它是什么的重要信息。如果不清楚变量的含义,至少注释变量赋值。


像这样改变你的循环:

$previousScore = null;    // added THIS
foreach ($totalSubMarks->result_array() as $tmrow) {

        $totalMarks = $this->student_model->getTotalMarksForStudnets($tmrow['subject_id'],
            $stdName['pstudent_id'], $table, $totField);
        // set mtotalmark

        $gtotal = $gtotal + $totalMarks;
        // set mgtotal
        $mGTotal[$idd] = $gtotal;

        if ($totalMarks != 0) {
            if($previousScore != $totalMarks) {    // added THIS
                $totSubjects = $totSubjects + 1;
            } else {                               // added THIS
                $totSubjects = $totSubjects;       // keep rank without incrementing
            }
        }
        $previousScore = $totalMarks;       // added THIS

        // set mAvg
        if ($totSubjects != 0) {
            $mAvg[$idd] = round($gtotal / $totSubjects, 1);
        } else {
            $mAvg[$idd] = 0;
        }
    }

如果$gtotal 或任何其他神秘变量;) 持有分数,然后尝试将我给定的代码更改修改为$gtotal。应该不会太难。在这种情况下,只需添加评论,以便我可以更改我的答案,它实际上是正确的。

希望有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 2017-10-14
    • 2019-02-08
    • 2017-12-01
    • 1970-01-01
    相关资源
    最近更新 更多