话不多说,上代码,不懂原理与目的可以对照注释

/**
 * 根据给定的总数值返回每个单元的最值平均数
 *
 * @param integer $num 总共需要被平均的值
 * @param array   $data 提供的数据
 *
 * @example $num  = 12
 *           $data = [
 *                  "a" => 5,
 *                  "b" => 6,
 *                  "c" => 2,
 *                 ]
 *
 * @return [
 *          "a" => 5,
 *          "b" => 5,
 *          "c" => 2,
 *          ]
 */
if (! function_exists('get_avg_data')) {
    function get_avg_data($num, array $data)
    {
        $sum = array_sum($data);
        // 如果数组内小于需要数值
        if ($num >= $sum){
            $reData = $data;
        } else {
            asort($data);
            $reData = handle_avg_data($num, $data);
        }

        return $reData;
    }
}

// 处理数据
if (!function_exists('handle_avg_data')){
    function handle_avg_data(&$num, array &$data)
    {
        $n = count($data);
        $avg = (int)($num / $n);
        $y = $num % $n;
        $reData = [];
        $preData = $data;
        foreach ($data as $key => $value) {
            if ($value <= $avg){
                $reData[$key] = $value;
                unset($data[$key]);
                $num = $num - $value;
            }
        }
        if (count($preData) == count($data)){
            if ($y == 0){
                foreach ($data as $k => $v){
                    $reData[$k] = $avg;
                    unset($data[$k]);
                }
            } else {
                foreach ($data as $k => $v){
                    $reData[$k] = $avg + 1;
                    $num = $num -  $avg - 1;
                    unset($data[$k]);
                    break;
                }
            }
        }
        $reD = [];
        if (count($data) > 0){
            $reD = handle_avg_data($num, $data);
        }

        return array_merge($reData, $reD);
    }
}
好吧,再举一个例子

eg①:我总共需要30条数据,数据库中满足条件的有4类数据,他们总数分别是4,5,15,19条。
我要获得尽可能理想的数据,那么应该分别返回 4,5,11,10条。
eg②:我总共需要30条数据,数据库中满足条件的有4类数据,他们总数分别是12,6,15,19条。
我要获得尽可能理想的数据,那么应该分别返回 8,6,8,8条。
……

上面的代码就实现了这一目的。


yankeys
73 声望9 粉丝

相见,才知道被忙碌挤压的思念…