在由三个数组组成的数组中相等地分配项


Equal distribution of items in an array comprised of three arrays

假设有三个这样的数组:

$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');

每个数组可以包含0到12个元素。任务是收集一个最多包含12个项目的数组,该数组由这三个数组中平均分布的项目组成。在这个特定的示例中,需要的输出将是:

array("f1", "f2", "f3", "s1", "s2", "s3", "s4", "t1", "t2", "t3", "t4", "t5")

所以,理想情况下,最终的数组应该有每个数组的4个元素(12个想要的元素/3个数组=每个数组的4个元素)。在上面的例子中,因为第一个数组只有3个元素,所以我通过增加其他数组中的元素来"补偿"。

我想出了这个函数:

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 ^_^
    }
}

,调用它们的一种方式是:

$arrays = array("first" => $first, "second" => $second, "third" => $third);
$finalArr = calcArrays($arrays, 4);

因此,我创建了第一种情况,其中第一个数组具有最少的项数,然后是第二个,最后是第三个。正如你可以在其他两个if中看到我的评论——这只是必须以一种更好、更可读的方式来完成。因为,当然,如果我继续沿着这条路走下去,我可以做到这一点,但当我重新阅读代码时,我最终会讨厌自己。

那么,有人能指出我可能存在的算法问题,或者给出一些更好的方法来解决这个问题吗?

所以,理想情况下,最终的数组应该有每个数组的4个元素(12个想要的元素/3个数组=每个数组的4个元素)。在上面的例子中,因为第一个数组只有3个元素,所以我通过增加其他数组中的元素来"补偿"。

如果存在一个开放空间,哪个数组应该填充它?您可能希望空格均匀分布,那么我建议为此编写一个完整的类,分不同的步骤计算和创建结果。

对于您的示例,如果可能的话,让下面的数组填充遗漏的空格应该是可以的。于是任务就变得相当简单了。

$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);

由于您知道$max和输入数组的数量,因此事先计算$each很容易。现在,只要输入数组有项目并且结果需要项目,这个while()就会运行。如果项目的项目较少,$missing将继续进行下一次迭代。然而,如果最后一个数组的元素太少,这可能会遇到问题,但应该给你一个想法