I have two arrays that I would like to merge so that array A's first X amount elements are inserted first, then array B's Y amount of elements again and again until the new array contains all the elements from both arrays. If the number of elements in the arrays don't add up it should start merging from the beginning of the array again.
Something like this:
<?php
$arrA = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
$arrB = [1, 2, 3, 4];
# Print 2A 1B 2A 1B etc until no element is missing from the new array - as soon as new array contains all elements break
array_merge_interval($arrA, $arrB, 2, 1);
['A', 'B', 1, 'C', 'D', 2, 'E', 'F', 3, 'G', 'H', 4]
# Print 2B 1A 2B 1A etc until no element is missing from the new array - as soon as new array contains all elements break
array_merge_interval($arrB, $arrA, 2, 1);
[1, 2, 'A', 3, 4, 'B', 1, 2, 'C', 3, 4, 'D', 1, 2, 'E', 3, 4, 'F', 1, 2, 'G', 3, 4, 'H']
# Print 6B 0A etc until no element is missing from the new array - as soon as new array contains all elements break
array_merge_interval($arrB, $arrA, 6, 0);
[1, 2, 3, 4]
# Print 20A 3B etc until no element is missing from the new array - as soon as new array contains all elements break
array_merge_interval($arrA, $arrB, 20, 3);
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 1, 2, 3, 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 4]
I've tried a number of convoluted solutions with nested for(each) loops but I'm very unsatisfied (and unfinished) so I was hoping someone can come up with something smart using some to me unknown array function?
You could use this pair of functions:
function array_get_chunk($a, $size, &$i, &$leftOver) {
do {
$result[] = $a[$i % count($a)];
$i++;
if ($i <= count($a)) $leftOver--;
} while ($i % $size && $leftOver);
return $result;
}
function array_merge_interval($a, $b, $sizeA, $sizeB) {
if (!$sizeA && !$sizeB) return [];
if (!$sizeA) return $b;
if (!$sizeB) return $a;
$i = $j = 0;
$result = [];
$leftOver = count($a) + count($b);
do {
array_push($result, ...array_get_chunk($a, $sizeA, $i, $leftOver));
if ($leftOver) array_push($result, ...array_get_chunk($b, $sizeB, $j, $leftOver));
} while ($leftOver);
return $result;
}
The array_get_chunk function is a helper function. It takes an array, the chunk-size, the offset where the chunk should start, and the maximum number of not-yet-visited elements to allow to take.
The last two arguments are passed by reference, as they are updated by the function. The offset $i will increase and may go beyond the size of the array, so a modulo (%) is applied to map it to a valid array index. Only when that index is really within the range (without modulo) we consider that it is the first visit of an array element, and so only then $leftOver is decreased.
Once a complete chunk is produced, or the $leftOver variable reached 0, we return the chunk to the caller.
The main function array_merge_interval first checks for some easy border-cases, where one or both sizes are zero. Then it sets the $leftOver variable to the number of elements that are in both arrays together. This will ensure that the process will stop when all elements have been collected at least once.
The loop calls the helper function for each of both arrays, and adds the returned chunks to the final result, using array_push (and splash operator). This continues until $leftOver reaches 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With