Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I think this is close to what you ask: A constant, reasonably even distribution of the items in an array. </p> <pre><code>// The input array. 0s are regarded as blanks. $array = array(1,1,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); // Count the times each item occurs. PHP will probably have a function for that, but I don't know. $counter = array(); foreach ($array as $item) { // Zeros are infill. Don't process them now, only process the other numbers and // the zeros will occupy the remaining space. if ($item === 0) continue; if (!array_key_exists($item, $counter)) $counter[$item] = 0; $counter[$item]++; } // Reverse sort by quantity. This results in the best distribution. arsort($counter); // Pre-fill a new array with zeros. $resultCount = count($array); $result = array_fill(0, $resultCount, 0); // Distribute the items in the array, depending on the number of times they occur. foreach ($counter as $item =&gt; $count) { // Determine the division for this item, based on its count. $step = $resultCount / $count; // Add the item the right number of times. for ($i = 0; $i &lt; $count; $i++) { // Start with the index closest to the preferred one (based on the calculated step). $index = 0; $startIndex = (int)($step * $i); // Count up until a right index is found. for ($index = $startIndex; $index &lt; $resultCount; $index++) { if ($result[$index] === 0) { $result[$index] = $item; break; } } // If no proper index was found, count fown from the starting index. if ($index === $resultCount) { for ($index = $startIndex; $index &gt;= 0; $index--) { if ($result[$index] === 0) { $result[$index] = $item; break; } } } // Still no proper index found, that shouldn't be possible. There's always room. if ($index === -1) { throw new Exception('This cannot not happen'); } } } var_dump($result); </code></pre> <p>For array:</p> <pre><code>1,1,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 </code></pre> <p>It returns:</p> <pre><code>3,2,1,0,3,0,0,0,3,0,2,1,3,0,0,0,3,0,0,0,0,3,2,1,0,3,0,0,0,3,0,2,1,3,0,0,0,3,0,0,0,0 </code></pre> <p>For array:</p> <pre><code>1,1,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0 </code></pre> <p>It returns:</p> <pre><code>4,4,3,4,3,4,2,4,3,4,2,4,3,4,1,4,3,4,1,4,0,4,4,3,4,3,4,2,4,3,4,2,4,3,4,1,4,3,4,1,4,0 </code></pre> <p>Which I think is a neat distribution. Thanks to datdo for the idea of sorting the intermediate array.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload