Daric
Daric

Reputation: 16769

Sorting array keeping even values on top PHP

I have tried sorting the below array to keep the even values on top and in sorted order from asc to desc

$array = array(1,2,3,4,5,6,7,8,9,10);

I tried this to sort the array

usort($array, function($a, $b) { 
                    if ($a % 2 == 0 )
                    { 
                        return 1 ;
                    }
                    else 
                    { 
                        return -1;
                    }
            }
        );

I got the output like below

Array
(
    [0] => 7
    [1] => 9
    [2] => 1
    [3] => 5
    [4] => 3
    [5] => 2
    [6] => 4
    [7] => 6
    [8] => 8
    [9] => 10
)

And I want the output array to be

Array
(
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
    [5] => 1
    [6] => 3
    [7] => 5
    [8] => 7
    [9] => 9
)

The even and odd values should be sorted in asc to desc order but keep the even values on top of odd values

Upvotes: 3

Views: 1741

Answers (6)

Don't Panic
Don't Panic

Reputation: 41810

For the comparison function, first take the difference of the mod 2 values of the two numbers.

It will be -1, 0, or 1. If it's not zero, then one number is even and the other is odd, so you can return that value. (That will sort odds above evens.)

If it is zero, then either both numbers are even or both numbers are odd, and you need to take the difference of the two numbers to break the tie.

A concise way to write this is:

usort($array, function($a, $b) {
    return $a % 2 - $b % 2 ?: $a - $b;
});

To sort odd numbers at the beginning instead, swap $a and $b in the first comparison.

return $b % 2 - $a % 2 ?: $a - $b;

Upvotes: 0

bozdoz
bozdoz

Reputation: 12860

Short and simple way to write it:

<?php
$array = array(1,2,3,4,5,6,7,8,9,10);
usort($array, function($a, $b){
  if ($a % 2 == $b % 2) {
    return $a - $b;
  }
  return $a % 2 != 0;
});
print_r($array);
?>

or with a ternary:

<?php
$array = array(1,2,3,4,5,6,7,8,9,10);
usort($array, function($a, $b){
  return ($a % 2 == $b % 2) ? ($a - $b) : ($a % 2 != 0);
});
print_r($array);
?>

Upvotes: 1

Till Helge
Till Helge

Reputation: 9311

I think you need a somewhat more complex function. Because when you look at it there are different cases to take care of and in every one of them something different must happen:

  • $a and $b both are even: default numeric comparison
  • $a and $b both are odd: default numeric comparison
  • $a is even, $b is odd: $a is always smaller than $b
  • $a is odd, $b is even: $b is always smaller than $a

And for the implementation see the answer of fab.

Upvotes: 4

Mark Baker
Mark Baker

Reputation: 212412

usort($array, function($a, $b) { 
                    if ($a % 2 == $b % 2) {
                           if ($a == $b) {
                               return 0;
                           }
                           return ($a < $b) ? -1 : 1;
                    } elseif ($a % 2 == 0) { 
                        return -1 ;
                    } else { 
                        return 1;
                    }
            }
        );

Upvotes: 2

William Buttlicker
William Buttlicker

Reputation: 6000

A bit lenghty but works fine for me:

$array = array(1,2,3,4,5,6,7,8,9,10);

$even =array();

$odd = array();

foreach ($array as $item) {

  if($item%2==0) {

    $even[] = $item;
  }

  else {

    $odd[] = $item;

  }

}

usort($even);

usort($odd);

$array_sort = array_merge($even,$odd);

print_r($array_sort);

Upvotes: 2

Fabian Schmengler
Fabian Schmengler

Reputation: 24551

usort is not stable. The documentation states:

If two members compare as equal, their relative order in the sorted array is undefined.

So, what you can do is:

usort($array, function($a, $b) {
                if ($a % 2 == $b % 2) {
                    return intval($a - $b);
                }
                elseif ($a % 2 == 0 )
                { 
                    return -1 ;
                }
                else 
                { 
                    return 1;
                }
        }
    );

This compares the actual values if both are even or both are odd.

Upvotes: 7

Related Questions