从每个数组键中拆分多个阵列的平均值

时间:2013-07-25 19:00:10

标签: php arrays multidimensional-array

我不确定如何解释我想做的最佳方式。但是我要试一试! 我有一个像这样的数组:

$array = array(
    "a" => array(
         "key1" => 3,
         "key2" => 4,
         "key3" => 1
    ),
    "b" => array(
         "key1" => 4,
         "key2" => 5,
         "key3" => 2
    ),
    "c" => array(
         "key1" => 2,
         "key2" => 3,
         "key3" => 3
    ),
    "d" => array(
         "key1" => 1,
         "key2" => 2,
         "key3" => 2
    )
);

注意:数组会更大,值不会只是那些(但总是一个整数)。

如何将此数组分成两半,每个部分的每个不同键的平均值相似(key1的平均值相似,key2的类似平均值和key3的类似平均值)?

在上面的例子中,结果应为:

$array[0] = array(
    "a" => array(
         "key1" => 3,
         "key2" => 4,
         "key3" => 1
    ),
    "c" => array(
         "key1" => 2,
         "key2" => 3,
         "key3" => 3
    )
);

$array[1] = array(
    "b" => array(
         "key1" => 4,
         "key2" => 5,
         "key3" => 2
    ),
    "d" => array(
         "key1" => 1,
         "key2" => 2,
         "key3" => 2
    )
);

(两个数组的key1平均值为2.5,key2为3.5,key3为2)

1 个答案:

答案 0 :(得分:0)

以下功能改编自Hacker's Delight site

function combos($bits, $max=32){
    $out = array();
    if ($bits < 1 || $bits > $max || $max > 32) return $out;
    $x = pow(2, $bits) - 1;
    $last = $x * pow(2, ($max - $bits));
    while($x <= $last){
        $out[] = decbin($x);
        $smallest = ($x & -$x);
        $ripple = $smallest + $x;
        $new_smallest = ($ripple & -$ripple);
        $ones = (($new_smallest/$smallest) >> 1) - 1;
        $x = $ripple | $ones;
    }
    return $out;
}

以下功能是可选的。如果存在奇数个子数组,或者子数组中的项不相等,它会预先捕获数组。如果项目不相等,则用0填充子阵列。如果子数组的数量是奇数,则会添加一个带有零填充项目的数据:

function array_prep($arr){
    $cnt = 0;
    foreach ($arr as $key => $value){
        $cnt = (count($value) > $cnt) ? count($value) : $cnt;
    }
    if (count($arr)%2 == 1){
        $arr[] = array_fill(0, $cnt, 0);
    }
    foreach ($arr as $key => $value){
        $arr[$key] = array_pad($value, $cnt, 0);
    }
    return $arr;
}

这是平衡子阵列的主要代码:

$array = array_prep($array);//remove if prepping is unnecessary
$n = count($array);
$cmb = combos(floor($n/2), $n-1);
array_unshift($array, null);
$rows = call_user_func_array('array_map', $array);
array_shift($array);
$score = array_combine($cmb, array_fill(0, count($cmb), 0));
foreach ($rows as $key => $row){
    foreach ($score as $combo => $val){
        $c = str_split(str_pad($combo, $n, '0', STR_PAD_LEFT));
        $sc = 0;
        foreach ($row as $k => $i){
            $sc += $i*(1 - 2*$c[$k]);
        }
        $score[$combo] += abs($sc);
    }
}
$min = array_keys($score, min($score));
$winner = str_split(str_pad($min[0], $n, '0', STR_PAD_LEFT));
//hack to keep original keys associated with values
foreach ($winner as $key => $value){
    $winner[$key] = $n*$value + $key; 
}
$winner_copy = $winner;
$keys = array_keys($array);
array_multisort($winner, $array);
array_multisort($winner_copy, $keys);
$array = array_combine($keys, $array);
$arr1 = array_slice($array, 0, floor($n/2));
$arr2 = array_slice($array, floor($n/2));