You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

教学系统学生成绩排名功能优化:实现同分学生分配相同排名

Fixing Shared Ranks for Students with Same Scores in CodeIgniter

Let's adjust your function so students with identical average scores get the same rank. The core issue with your current code is that it increments the rank by 1 for every student, regardless of their score. Here's the modified version with explanations:

Modified Code

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); 
            $gtotal = $gtotal + $totalMarks; 
            $mGTotal[$idd] = $gtotal; 
            if ($totalMarks != 0) { 
                $totSubjects = $totSubjects + 1; 
            } 
            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 (! is_nan($val)) { 
            $nums[$dd] = $val; 
        } 
    } 
    arsort($nums); 

    // --- Updated ranking logic ---
    $previous_avg = null;
    $current_rank = 1;
    $position_index = 1;

    foreach ($nums as $kk => $av) {
        // Only update rank when the current score is different from the previous
        if ($previous_avg !== null && $av != $previous_avg) {
            $current_rank = $position_index;
        }

        // Return the rank if we found the target student
        if ($student_id == $mId[$kk]) {
            return $current_rank;
        }

        $previous_avg = $av;
        $position_index++;
    }

    // Fallback if the student isn't found in the list
    return null;
}

Key Changes Explained

  1. Track Previous Score: We added $previous_avg to compare the current student's average with the last one processed. This lets us detect when scores are the same and keep the rank consistent.
  2. Separate Rank and Position:
    • $current_rank is the actual rank we'll return (shared for identical scores).
    • $position_index counts every student processed. When a new score is detected, we set $current_rank to $position_index—this ensures ranks skip ahead for students after a group of high-scorers (e.g., 3 students with rank 1 will make the next student rank 4, which follows standard competitive ranking rules).
  3. Cleaned Unused Code: The inner loop over $totalSubMarks in the ranking phase was redundant (it didn't use the $totalMarks value), so we removed it to boost performance and simplify the code.

Alternative Ranking (No Skipping)

If you prefer that ranks don't skip after a group of students with the same score (e.g., 3 students rank 1, next student ranks 2), use this simplified ranking logic instead:

// Alternative ranking logic
$previous_avg = null;
$current_rank = 1;

foreach ($nums as $kk => $av) {
    if ($previous_avg !== null && $av != $previous_avg) {
        $current_rank++;
    }

    if ($student_id == $mId[$kk]) {
        return $current_rank;
    }

    $previous_avg = $av;
}

Pick the version that matches your school's ranking policy!

内容的提问来源于stack exchange,提问作者MaryUghojor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:42:37