在由三个数组组成的数组中的项目的相等分布

时间:2014-06-14 20:49:56

标签: php algorithm

假设您有三个这样的数组:

$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个项目,我补偿了#34;增加其他数组中的项目数。

我想出了这样做的功能:

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

所以,我做了第一个案例场景,第一个数组的项目数最少,然后是第二个,最后是第三个。正如你可以在其他两个ifs中看到我的评论 - 这只需要以更好,更易读的方式完成。因为,如果我继续沿着这条路走下去,我可以做到这一点,但在重读代码时我最终会讨厌自己。

那么,有人能指出我可能存在的算法问题,或者就如何处理这个问题给出一些更好的想法吗?

1 个答案:

答案 0 :(得分:2)

  

因此,理想情况下,最终数组应该包含每个数组的4个项目(12个需要项目/ 3个数组=每个数组中有4个项目)。在上面的例子中,因为第一个数组只有3个项目,我补偿了#34;增加其他数组中的项目数。

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

举个例子,如果可能的话,让以下数组填充错过的空格应该没问题。那么任务变得非常简单。

$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会将该项目带到下一次迭代。但是,如果最后一个数组的项目太少但是应该给你一个想法,那么这可能会遇到问题