2016-04-05 1 views
-1

У меня есть массив, который может быть разделен на 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 разных массива и объединить их снова попарно по отношению к их размеру. Но с группами, которые имеют отношение около, 5, я заканчиваю тем, что в конце блок из одной группы.

+0

Я использую php 5.2.6 – Kana

+0

Это не PHP, это JSON. – Anthony

+2

Разве это не вариант https://en.wikipedia.org/wiki/Graph_coloring? – Tibrogargan

ответ

0

EDIT: Адаптирован ответ в соответствии с комментариями ОП о том, как он хочет обрабатывать оставшиеся предметы. Сохраняя свой первоначальный ответ ниже.

Мы распространять самую большую группу равномерно друг с другом, вычисляя, сколько мы можем поставить в каждом и с использованием некоторых промежуточных массивов:

<?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>'; 
?> 

Однако, если одна группа явно превосходит другие (например, с oconut в моем примере), вы закончите с кучей кокосов в конце.

Надеюсь, это помогло.

+0

Спасибо, но тогда это будет почти такой же результат, как и в моей версии. Как я уже сказал, я тоже закончил с блоком одной группы в конце. – Kana

+0

Ну, на самом деле нет способа избежать этого, если у вас есть одна группа, которая превосходит остальных. Что вы хотите делать с дополнительными элементами? – Growiel

+0

Они должны распределяться равномерно по всему массиву. Вместо того, чтобы: кокоса - самолет - банан - кокосовый орех - банан - кокосовый орех - банан - кокосовый орех - кокосовый орех - кокосовый орех ... Это должно привести к: кокоса - самолет - кокосовое - банановый - кокосовое - кокосовое - банановый кокоса - coconut - banana – Kana

Смежные вопросы