我不确定如何解释我想做的最佳方式。但是我要试一试! 我有一个像这样的数组:
$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)
答案 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));