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:
- Determine how many lessons per student, or students per lesson
- 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.