我有一个数组可以通过其中一个属性分成3个不同的组:
$shuffleMeGood = array(
0 => array('id' => '1', 'group' => 'banana'),
1 => array('id' => '2', 'group' => 'banana'),
2 => array('id' => '3', 'group' => 'banana'),
3 => array('id' => '4', 'group' => 'airplane'),
4 => array('id' => '5', 'group' => 'coconut'),
5 => array('id' => '6', 'group' => 'coconut')
...
);
组的大小可以变化,可以有7个椰子元素和5个飞机元素等等。如何以同一组中没有或最不可能出现的邻居的方式对阵列进行洗牌?
我试图将它们分成3个不同的数组,然后按照它们的大小比例再次合并它们。但是对于比率接近的组,我最终会在一个组中有一个组。
答案 0 :(得分:0)
编辑:根据OP对如何处理剩余项目的评论调整答案。保留我原来的答案。
我们将通过计算每个组中可以放入的数量并使用一些中间数组来均匀地分配最大的组:
<?php
// Your array changed to PHP with some added items
$a = array(
array(
'id'=>1,
'group'=>'banana'
),
array(
'id'=>2,
'group'=>'banana'
),
array(
'id'=>3,
'group'=>'banana'
),
array(
'id'=>4,
'group'=>'airplane'
),
array(
'id'=>5,
'group'=>'coconut'
),
array(
'id'=>6,
'group'=>'coconut'
),
array(
'id'=>7,
'group'=>'coconut'
),
array(
'id'=>8,
'group'=>'coconut'
),
array(
'id'=>9,
'group'=>'coconut'
),
array(
'id'=>10,
'group'=>'coconut'
),
);
// We want to know each of group there are
// We also want to arrange the items in a new "perGroup" array.
$counts = array();
$perGroup = array();
foreach($a as $key=>$value){
// Avoid PHP undefined notices
if(isset($counts[$value['group']])){
$counts[$value['group']]++;
}else{
$counts[$value['group']] = 1;
}
// Avoid PHP undefined notices
if(isset($perGroup[$value['group']])){
$perGroup[$value['group']][] = $value;
}else{
$perGroup[$value['group']] = array();
$perGroup[$value['group']][] = $value;
}
}
// Sort the count from largest to lowest
arsort($counts);
// Get all the group names
$keys = array_keys($counts);
// We'll have as many unique groups as the SECOND largest item.
$nbOfUniques = $counts[$keys[1]];
// Calculate how many of the largest we need to put in each unique
$nbOfLargestPerUnique = ceil($counts[$keys[0]] / $nbOfUniques);
// Get the largest group name for easier use
$largestGroupName = $keys[0];
$finalArray = array();
// Loop for how many unique groups we have
for ($i = 1; $i <= $nbOfUniques; $i++) {
// For each group...
foreach($keys as $k=>$v){
// If its the largest
if($v == $largestGroupName){
// Add as many as needed
for ($j = 1; $j <= $nbOfLargestPerUnique; $j++) {
// Make sure we actually have an item, as the number is not always exact.
// Using array_shift() to reduce our array
if(($item = array_shift($perGroup[$v])) !== NULL){
$finalArray[] = $item;
}
}
}else{
// Not the largest group, just add one
if(($item = array_shift($perGroup[$v])) !== NULL){
$finalArray[] = $item;
}
}
}
}
echo '<pre>';
var_dump($finalArray);
echo '</pre>';
?>
<强> ORIGINAL:强> 我将使用一个带有两个数组的递归函数:最后一个,以及在我们处理所有数据之前变得越来越小的初始数据的副本:
<?php
// Your array changed to PHP with some added items
$a = array(
array(
'id'=>1,
'group'=>'banana'
),
array(
'id'=>2,
'group'=>'banana'
),
array(
'id'=>3,
'group'=>'banana'
),
array(
'id'=>4,
'group'=>'airplane'
),
array(
'id'=>5,
'group'=>'coconut'
),
array(
'id'=>6,
'group'=>'coconut'
),
array(
'id'=>7,
'group'=>'coconut'
),
array(
'id'=>8,
'group'=>'coconut'
),
array(
'id'=>9,
'group'=>'coconut'
),
array(
'id'=>10,
'group'=>'coconut'
),
);
// Our recursive function
// $array is the array to be ordered (in our case, $a)
// $orderedArray is needed for the recusivity part
function orderArray($array, $orderedArray = array()){
// Remember the last processed group
$lastGroup = '';
// Loop on all $array's items
foreach($array as $key=>$value){
// If NOT the same as the last group
if($value['group'] != $lastGroup){
// Add it to our orderedArray
$orderedArray[] = $value;
// Remember its group
$lastGroup = $value['group'];
// Remove it from the original array, as it has already been processed
unset($array[$key]);
}
}
// There are still items to be processed
if(count($array) > 0){
// Call ourselves again, with the same arrays
return orderArray($array, $orderedArray);
}else{
// Done processing, return the $orderedArray
return $orderedArray;
}
}
echo '<pre>';
var_dump(orderArray($a));
echo '</pre>';
?>
然而,如果一个群体明显超过其他群体(例如我的例子中的椰子),那么最终你会得到一堆椰子。
希望它有所帮助。