0

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

2

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is truely amazing, I thank you so much for all your help, and the demo was awesome, thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.