2016-11-22 65 views
3

我有一個列表,說40個按字母順序排列的術語我想以相似大小的組進行分割,同時通過開始字母來保持分組。在php中分配類似大小的塊的項目7

的目標是創建多個數據塊,指示每個塊的起始字母頭一個字母列表,像A-DE-H

我想過繼續這樣。通過多維數組首字母

$terms = array('Archers','Arrows','Bees' [etc...]); 

然後將它們分組:與列表開始

$terms = array(
    'a' => array('Archers','Arrows'), 
    'b' => array('Bees'), 
    // [..etc..] 
    'z' => array('Zebras','Zebus') 
); 

然後重新組這個多維數組分成四組是同樣大小。類似的東西:

$termgroups = array(
    // first group with e.g. 12 items 
    'A-C' => array(
     'a' => array('Archers','Arrows'), 
     'b' => array('Bees') 
), 
    // second group with e.g. 9 items 
    // ...etc... 
); 

但是,這將意味着很多計數,迭代的,也許做出的第一次嘗試,然後在整個東西去一次。

我不知道如何處理這個任務,我感覺它已經做了很多次 - 但我不知道如何調用它。

你會怎麼做?

+2

對於第二分組您可能希望瞭解線性劃分方法 – Paul

回答

2

這不是一件小事。這是another question about linear partitioning。幸運的是,您可以在那裏找到該算法的PHP實現。所以具有,你的問題歸結爲尋找方式來使用現有的解決方案:

sort($terms); 

$mappedToFirstLetter = array_reduce(
    $terms, 
    function ($mappedToFirstLetter, $term) { 
     $letter = strtolower(substr($term, 0, 1)); 

     if (!isset($mappedToFirstLetter[$letter])) { 
      $mappedToFirstLetter[$letter] = []; 
     } 

     $mappedToFirstLetter[$letter][] = $term; 

     return $mappedToFirstLetter; 
    }, 
    [] 
); 

// Count words for each letter in order to use 
// linear partition algorithm. 
$countByLetters = array_values(array_map('count', $mappedToFirstLetter)); 

$numberOfGroups = 4; 

$groups = linear_partition($countByLetters, $numberOfGroups); 

// Group words using linear partition algorithm results. 
$chunked = array_reduce(
    $groups, 
    function ($chunked, $group) use (&$mappedToFirstLetter) { 
     // Get portion of words. 
     $chunk = array_reduce(range(1, count($group)), function ($chunk) use (&$mappedToFirstLetter) { 
      $chunk[key($mappedToFirstLetter)] = array_shift($mappedToFirstLetter); 
      return $chunk; 
     }, []); 

     // Generate group name using chunk keys. 
     $key = preg_replace_callback(
      '/^([a-z])(?:([a-z]*)([a-z]))?$/', 
      function ($matches) { 
       $matches = array_pad($matches, 4, ''); 
       return $matches[1] . ($matches[3] ? '-' : '') . $matches[3]; 
      }, 
      implode('', array_keys($chunk)) 
     ); 
     $chunked[$key] = $chunk; 

     return $chunked; 
    }, 
    [] 
); 

你可以找到所提到問題的答案之間linear_partition功能。

這裏是working demo

順便說一句,這樣的問題通常有一個獎金,因爲,正如我寫的,這不是一個微不足道的任務。甚至更進一步,這不是一個真正的問題,而是一個問題。這不是一個答案,而是問題的解決方案。但是,由於沒有很多有趣的問題,所以不會回答這個問題。

+0

你是對的 - 真正的問題是有點「請編寫它爲我」 -ish :-) - 我是不是真的,如果確定我應該這樣問。發佈後不能立即設置賞金。我認爲SO應該可以通過貨幣化,但這可能永遠不會發生。 – Urs

+0

我期待着實現這一點,非常感謝! :-))) – Urs

0

爲此,我創建了兩個函數a2z($terms)chankItems($terms,$chunkList)。如果你調用chunkItem函數,那麼它將調用a2z函數並將原始數組固定爲一個帶有一個z鍵的數組。

爲了測試目的,我生成了a-z單詞列表。

// use this section for generate sample data set 
// only testing purpose 
$terms = array(); 
foreach(range('A', 'Z') as $key){ 
    foreach (range(1, 3) as $value) { 
     $terms[] = $key."word".$value; 
    } 
} 

// get output with a to z keys 
$termsAtoZ = a2z($terms); 
// print a to z output 
echo "<pre>"; 
print_r($termsAtoZ); 
echo "</pre>"; 

// chunk array(expect to chunk) 
$chunkList = array('A-D', 'E-I', 'J-Z'); 

// Get output as chunk 
// $terms - orginal array 
$termsChunk = chunkItems($terms,$chunkList); 
// print chunked output 
echo "<pre>"; 
print_r($termsChunk); 
echo "</pre>"; 

// use function generate output with a to z keys 
function a2z($terms){ 
    // sort terms array a to z 
    sort($terms); 
    // a - z keys array 
    $a2z = array(); 
    foreach ($terms as $word) { 
     $key = str_split($word)[0]; 
     $a2z[strtolower($key)][] = $word; 
    } 
    return $a2z; 
} 

// use this function for generate chunks array 
// example A-C, D - G 
function chunkItems($terms,$chunkList){ 
    // get a-z format array output 
    $a2zFormatList = a2z($terms); 
    $chunkArray = array(); 
    // loop chunk list 
    foreach($chunkList as $chunk){ 
     // loop chunk first letter to end letter 
     foreach(range(strtolower(str_split($chunk)[0]), strtolower(str_split($chunk)[2])) as $letter){ 
      // if letter exist in a - z array, then copy that key's array to output 
      if (array_key_exists($letter, $a2zFormatList)) { 
       $chunkArray[$chunk][$letter] = $a2zFormatList[$letter]; 
      } 
     } 
    } 
    return $chunkArray; 
}