Sorting a PHP array in a discontinuous manner I start with an array containing some 'ids' and some 'values'.

What I need is to organize the 'ids' in a new array to be, if possible, apart when the 'values' they are associated with are alike.

So I came up with a solution.  If there is too much of a value type, the spreading is uneven.  So if one of you has a different, better, solution, I'm all ears!

Here is what I came up with:

function discontinus_sort($to_sort, $order_by, $id){

    while (count(array_count_values($to_sort)) &gt;1) {

    $order[] = [$id =&gt; key($to_sort) , $order_by =&gt; $to_sort[key($to_sort)]];

    $holder = $to_sort[key($to_sort)];

    unset($to_sort[key($to_sort)]);

    reset($to_sort);

        if (isset($to_sort[key($to_sort)])) {

            while( $holder == $to_sort[key($to_sort)] ) {
            next($to_sort);
            }
        }
    }

while ($to_sort) {

    $order[] = [$id =&gt; key($to_sort) , $order_by =&gt; $to_sort[key($to_sort)]];

    unset($to_sort[key($to_sort)]);

}

return $order;

}


And for an example:

$test[0=&gt;'red',1=&gt;'red',2=&gt;'red',3=&gt;'crimson',4=&gt;'aqua',5=&gt;'chartreuse',6=&gt;'green',7=&gt;'chartreuse',8=&gt;'red',9=&gt;'crimson',10=&gt;'crimson',11=&gt;'aqua',12=&gt;'aqua',13=&gt;'green',14=&gt;'crimson'];


$test_order = discontinus_sort($test, 'couleur', 'id');

foreach ($test_order as $key) { 

echo '&lt;div style="height: 100px; width: 100px; margin:5px; float: left; background-color:'.$key['couleur'].'; " &gt;&lt;/div&gt;';
}


If you change too many values, let's say by red, you'll end up with a big stack of red at the end.
Maybe this answer is a bit late, but hopefully someone can benefit from it!

First off, very interesting concept... It was a challenge to try and figure this one out! I have come up with another implementation, whether it's truly better or not is for the author to decide. Here it is:

&lt;?php

function discontinuous_sort($input) {
    $new = array();

    while ($input) {
        $curr = current($input);
        if (end($new) == $curr) {
            next($input);
            continue;
        } else {
            $new[] = $curr;
            unset($input[key($input)]);
            reset($input);
        }
    }
    return array_filter($new);
}

$test = array('red', 'red', 'red', 'crimson', 'aqua', 'chartreuse', 'green', 'chartreuse', 'red', 'crimson', 'crimson', 'aqua', 'aqua', 'green', 'crimson');


$test_order = discontinuous_sort($test);

foreach ($test_order as $key) { 
    echo '&lt;div style="height: 100px; width: 100px; margin:5px; float: left; background-color:'.$key.'; " &gt;&lt;/div&gt;';
}


I'll see what I can do to explain things.

In all honesty, looking at your algorithm, I knew things could be changed. Sorry for making it so drastic!


The first thing I knew I could do was take away the manual indexing on the input array. It does us no good to do this. This also means I can take away the last two parameters in your function. We shouldn't need to name them or create a  multidimensional array.
You were onto something with the while loop, it just needed something else!
I've taken away the aspect of a "holder". At first I thought I'd need one too, but after more work it became apparent I didn't. I am just utilizing the array positioning functions in a different manner.
My snippet basically works like this: 

While the original array exists, begin a check. Check if the last element of the new array is equal to the current element in the original. If it is, move onto the next element so we don't get two identical elements next to each other. If the last element isn't equal to the current, append it to the new array and delete that element from the original. Then go back to the beginning! Lastly, erase any empty values (empties are made when we have lots of reds or whatever).


And that's it! I'm sure mine could be simplified, but we're not Code Golf here! ;)