Amirabbas asadi
Amirabbas asadi

Reputation: 300

Sort a flat array to alternate values

I have a flat array of values which may only be 1 or 0. How can I sort the array so that the values alternate for as long as posible starting with a 1 value (if one exists)?

Input:

$array = [
    'a' => 0,
    'b' => 0,
    'c' => 0,
    'd' => 1,
    'e' => 1,
    'f' => 1
];

Expected result:

[
    'd' => 1,
    'a' => 0,
    'e' => 1,
    'b' => 0,
    'f' => 1,
    'c' => 0,
]

Another input:

$array = [1,0,0,0,0,1,1,0,0,0,0,0,0];

Expected result:

[
    0 => 1,
    1 => 0,
    2 => 1,
    3 => 0,
    4 => 1,
    5 => 0,
    6 => 0,
    7 => 0,
    8 => 0,
    9 => 0,
    10 => 0,
    11 => 0,
    12 => 0,
]

Upvotes: -1

Views: 694

Answers (2)

mickmackusa
mickmackusa

Reputation: 47904

Populate an array of values occurrences then use array_multisort() to first sort by that array, then by value descending so that 1's come before 0's. Demo

$counters = [0, 0];
$nths = [];
foreach ($array as $v) {
    $nths[] = $counters[$v]++;
}

array_multisort($nths, $array, SORT_DESC);
var_export($array);

Or in a functional style: Demo

array_multisort(
    array_map(
        function ($v) {
            static $counters = [0, 0];
            return $counters[$v]++;
        },
        $array
     ),
     $array,
     SORT_DESC
);
var_export($array);

Upvotes: 1

CrayonViolent
CrayonViolent

Reputation: 32532

Here's my take..

// example array
$array = array('d'=>1,'a'=>0,'b'=>0,'c'=>0,'e'=>1,'f'=>1,'g'=>1,'h'=>1);

$temp=array();
$result=array();
foreach ($array as $k=>$v) {
  if ($v%2==0)
    $temp[0][$k]=$v;
  else
    $temp[1][$k]=$v;
}
$c = max(count($temp[0]),count($temp[1]));
for ($i=0;$i<$c;$i++) {
  $ok = key($temp[1]);
  if ($ok) {
    $result+=array($ok=>$temp[1][$ok]);
    next($temp[1]);
    $ok=false;
  }
  $ek = key($temp[0]);
  if ($ek) {
    $ek = key($temp[0]);
    $result+=array($ek=>$temp[0][$ek]);
    next($temp[0]);
    $ek=false;
  }
}

print_r($result);
// Array ( [d] => 1 [a] => 0 [e] => 1 [b] => 0 [f] => 1 [c] => 0 [g] => 1 [h] => 1 )

Upvotes: 1

Related Questions