2

So I have a

student model, subject model, marks model, which has the total score field

what I am trying to do is get the total score in an exam for each student in a class and then retrieve the results according to the highest score in the class and then position those scores as 1,2,3...

then finally get the position a single student and store it in an exam record table.

so far I was able to achieve getting the total score in an exam for each student, stored them in an array, sorted them according to the highest score,

the only issue now giving me a headache is getting the position of those scores from the array, my question is how can I get the position of a score for a student, or is there a way to add the positions to the scores and then retrieve the position for a student

For example

1 student_id  => 2,  total_score => 500 
2  student_id => 3, total_score => 455
3  student_id => 5, total_score =>  345

here is my code below, Please anyone with an idea how to solve this I need your help.

TextInput::make('position')->numeric(
            function (Closure $set) {
            // Get all students from class
            $studentsInClass = $this->class->students;
            
            //empty array to store student's total_score
            $totalScore = [];
            
           // loop through students get all their total_score on all subjects from mark table and sum it, then store it 
           in totalScore array.
            foreach ($studentsInClass as $key => $student) {
              
          $totalScore[] = array('student_id' => $student->id, 'total_score' => $student->marks->sum('total_score') );
            }
            // Sort scores from highest to lowest
            $sortedScores= array_values(array_reverse(Arr::sort($totalScore, function ($value) {
                return $value['total_score'];
            })));

            // get the current student Id 
            $id = $this->student->id;
            // find a student in the array that matches the current student id and return his score.
            //so this is where I would like to return the score and position of the student 
            $filteredArray = Arr::where($sortedScores, function ($value, $key) use ($id) {
                return $value['student_id'] == $id;
            });
          
        }
        )->disabled(),

if you dd($sortedScores)

enter image description here

Adam
  • 85
  • 2
  • 12
  • 1
    Well in `foreach ($studentsInClass as $key => $student)` the `$key` is the the index of the array item which is also the position of the student. Just put the `$key` in your `$totalScore` array as `student_position`. – Mehyar Sawas Jan 03 '23 at 22:20
  • Ignore your code for moment. Post the table data and what you need. – Abdulla Nilam Jan 04 '23 at 04:19
  • @MehyarSawas I tried to do that but problem is that because I am sorting the score based on the highest to lowest the index is not serial, it comes as 3,0,2 like that. What I need is for the index to be serially even when the score is sorted base on highest score, – Adam Jan 04 '23 at 08:12

3 Answers3

2

You have a two-dimensional array.

$sortedScores = [
  ['student_id'  => 2, 'total_score' => 443],
  ['student_id'  => 4, 'total_score' => 410],
  ['student_id'  => 1, 'total_score' => 371],
  ['student_id'  => 3, 'total_score' => 170],
];

The index of each row is already consecutive from 0-3. I think you want to add a rank to the rows.

foreach($sortedScores as $idx => $row)
  $sortedScores[$idx]['rank'] = $idx+1;

//test output
var_export($sortedScores);

Output:

array (
  0 => 
  array (
    'student_id' => 2,
    'total_score' => 443,
    'rank' => 1,
  ),
  1 => 
  array (
    'student_id' => 4,
    'total_score' => 410,
    'rank' => 2,
  ),
  2 => 
  array (
    'student_id' => 1,
    'total_score' => 371,
    'rank' => 3,
  ),
  3 => 
  array (
    'student_id' => 3,
    'total_score' => 170,
    'rank' => 4,
  ),
)

If you want rank to start at 0, just assign $idx.

Try on https://3v4l.org/9Dv7D

I hope this helps and that I understood your problem correctly.

To find the key for a specific value in a multidimensional array see 'PHP Multidimensional Array Searching (Find key by specific value)'

jspit
  • 7,276
  • 1
  • 9
  • 17
  • wow! you absolutely understood the problem and your solution is perfect, thank you a million times. – Adam Jan 04 '23 at 13:43
1

You can use the array_search() function. This will either return the key of the value you are looking for or false if it is not in the array.

$letters = ['a', 'b', 'c', 'd'];
$key = array_search('b', $letters);
//In this case $key will equal to 2.
  • I tried that but keep getting fasle as returned value, even though the id is in the array. – Adam Jan 04 '23 at 08:14
  • 1
    array_search can only be used for one-dimensional arrays – jspit Jan 04 '23 at 12:17
  • Oh yeah my bad. I forgot about that part. I had the same problem too quite some time ago. The marked answer on this question should do the trick. [PHP multidimensional array search by value](https://stackoverflow.com/questions/6661530/php-multidimensional-array-search-by-value) – Doppelbemme Jan 04 '23 at 16:20
0

Presuming that $filteredArray contains a single item, then the first key should be the student's position in the sorted array.

$position = array_keys($filteredArray)[0];
Elliot
  • 73
  • 6