Reputation: 15038
Say you have three arrays like this:
$first = array('f1', 'f2', 'f3');
$second = array('s1', 's2', 's3', 's4', 's5');
$third = array('t1', 't2', 't3', 't4', 't5', 't6', 't7', 't8', 't9', 't10', 't11', 't12');
Each array can have from 0 to exactly 12 items. The task is to gather an array of maximum 12 items which compose of equally distributed number of items from these three arrays. In this particular example the wanted output would be:
array("f1", "f2", "f3", "s1", "s2", "s3", "s4", "t1", "t2", "t3", "t4", "t5")
So, the final array should ideally have 4 items of each array (12 wanting items / 3 array = 4 items from each array). In the upper example since the first array has only 3 items I "compensate" with increasing the number of items from other arrays.
I came up with the function to do this:
function calcArrays($arrays, $minItems){
$finalArr = array();
$first = $arrays["first"];
$firstCount = count($first);
$second = $arrays["second"];
$secondCount = count($second);
$third = $arrays["third"];
$thirdCount = count($third);
$totalCount = $firstCount + $secondCount + $thirdCount;
if ($totalCount == 0){
return array();
}
if ($totalCount == 36){
for($i=0; $i<$minItems; $i++)
$finalArr[] = $first[$i];
for($i=0; $i<$minItems; $i++)
$finalArr[] = $second[$i];
for($i=0; $i<$minItems; $i++)
$finalArr[] = $third[$i];
return $finalArr;
}
if ($firstCount < $secondCount && $firstCount < $thirdCount){
if ($firstCount < $minItems){
for ($i=0; $i<$firstCount; $i++)
$finalArr[] = $first[$i];
}
else{
for ($i=0; $i<$minItems; $i++)
$finalArr[] = $first[$i];
}
if ($secondCount < $thirdCount){
if ($secondCount < $minItems){
for ($i=0; $i<$secondCount; $i++)
$finalArr[] = $second[$i];
}
else{
for ($i=0; $i<$minItems; $i++)
$finalArr[] = $second[$i];
}
$howManyLeftTillFull = count($arrays) * $minItems - count($finalArr);
if ($thirdCount < $howManyLeftTillFull){
for ($i=0; $i<$thirdCount; $i++)
$finalArr[] = $third[$i];
}
else{
for ($i=0; $i<$howManyLeftTillFull; $i++)
$finalArr[] = $third[$i];
}
}
else{
if ($thirdCount < $minItems){
for ($i=0; $i<$thirdCount; $i++)
$finalArr[] = $third[$i];
}
else{
for ($i=0; $i<$minItems; $i++)
$finalArr[] = $third[$i];
}
$howManyLeftTillFull = count($arrays) * $minItems - count($finalArr);
if ($secondCount < $howManyLeftTillFull){
for ($i=0; $i<$secondCount; $i++)
$finalArr[] = $second[$i];
}
else{
for ($i=0; $i<$howManyLeftTillFull; $i++)
$finalArr[] = $second[$i];
}
}
return $finalArr;
}
else if ($secondCount < $firstCount && $secondCount < $thirdCount){
//note to myself: there's gotta be a better way :/
}
else if ($thirdCount < $firstCount && $thirdCount < $secondCount){
//see the upper note to yourself and just don't go this way ^_^
}
}
and a way to call them would be:
$arrays = array("first" => $first, "second" => $second, "third" => $third);
$finalArr = calcArrays($arrays, 4);
So, I made the first case scenario where the first array has the smallest number of items, then follows the second and finally the third. As you can see my comment in the other two else ifs - this just has to be done in a better and more readable way. Because, sure, I can make this work if I continue down this path but I would eventually hate myself when rereading the code.
So, can someone point me in the maybe existing algorithmic problem or give some better idea in how to approach this?
Upvotes: 0
Views: 580
Reputation: 10638
So, the final array should ideally have 4 items of each array (12 wanting items / 3 array = 4 items from each array). In the upper example since the first array has only 3 items I "compensate" with increasing the number of items from other arrays.
If an open space exists, which array should fill it? You might want spaces to be equally distributed, then I would suggest writing a complete class for this, calculating and creating the result in different steps.
Given your example, it should be okay to let the following array fill the missed spaces if possible. The task becomes quite simple then.
$data = array(
array('f1', 'f2', 'f3'),
array('s1', 's2', 's3', 's4', 's5'),
array('t1', 't2', 't3', 't4', 't5', 't6', 't7', 't8', 't9', 't10', 't11', 't12')
);
$max = 12;
$each = $max / count($data);
$result = array();
$missing = 0;
foreach ($data as $set) {
$missing += $each;
while (count($set) > 0 && $missing > 0) {
$result[] = array_shift($set);
$missing--;
}
}
print_r($result);
Since you know $max
and the number of input arrays, calculating $each
is easy beforehand. Now this while()
will go as long as the input array has items and result needs items. If the item has less items, $missing
will carry that on to the next iteration. This might however run into problems if the last array has too little items but should give you an idea
Upvotes: 2