Home > front end >  PHP 2 array loops - mixing up
PHP 2 array loops - mixing up

Time:08-21

I have a bit of a stange request, so I have 2 arrays

$students = array (
array(
"id" => 1,
"name" => "Sarah",
"grade" => "B"
),
array(
"id" => 2,
"name" => "David",
"grade" => "D"
)
);

and

$lessons = array (
array(
"id" => 1,
"name" => "Maths",
"grade" => "005"
),
array(
"id" => 2,
"name" => "English",
"code" => "003"
),
array(
"id" => 3,
"name" => "Science",
"code" => "007"
),
array(
"id" => 4,
"name" => "Music",
"code" => "001"
)
);

Normally, I use something like

foreach($students as $student)
{
    echo '<h1>'.$student['name'].' - '.$student['grade'].'</h4>';
}

to loop through the arrays, and this is good for certain things.

Please be mindful that sometimes I have only 1 student in the "students" array, sometimes around 30, and sometimes I have 1 lesson in the "lessons" array and sometimes 50.

But in my example, I have just included 2 students and 4 lessons.

So what I would like to do, is combine those 2 arrays and create an output that looks something like

Sarah
Maths
English
David
Science
Music

If I happened to have 5 students and 2 lessons, it would look like

Student
Student
Lesson
Student
Student
Lesson
Student

If I had 2 students and 2 lessons, it would look like

Student
Lesson
Student
Lesson

If I had 3 students and 1 lesson, it would look like

Student
Lesson
Student
Student

and if I just had 2 students and no lessons, it would look like

Student
Student

it's pretty hard for me to explain what this kind of sorting is called

Any help would be amazing, i'm bashing my head trying to work out how to adapt the foreach loop

CodePudding user response:

I think there are two parts to this:

  1. Determine how many lessons per student, or students per lesson
  2. Use that ratio to output an interleaved list

If we use whole-number division to divide the larger number by the smaller, we get our ratio; we just need to keep track of which around it was:

$numStudents = count($students);
$numLessons = count($lessons);

if ( $numLessons >= $numStudents ) {
    $studentSliceSize = 1;
    $lessonSliceSize = intdiv($numLessons, $numStudents);
}
else {
    $studentSliceSize = intdiv($numStudents, $numLessons);
    $lessonSliceSize = 1;
}

Now, we can take slices of each array, "unpack" them with the ... operator, and push them onto the end of a combined list:

$combinedArray = [];

$nextStudent = 0;
$nextLesson = 0;

while ( $nextStudent < $numStudents || $nextLesson < $numLessons ) {
    $studentSlice = array_slice($students, $nextStudent, $studentSliceSize);
    array_push($combinedArray, ...$studentSlice);
    $nextStudent  = $studentSliceSize;
    
    $lessonSlice = array_slice($lessons, $nextLesson, $lessonSliceSize);
    array_push($combinedArray, ...$lessonSlice);
    $nextLesson  = $lessonSliceSize;
}

Here is a live demo putting that together into a function.

  • Related