I have a simple array that looks like this:
array (size=6)
0 =>
array (size=2)
'id' => int 1
'primary' => boolean false
1 =>
array (size=2)
'id' => int 2
'primary' => boolean false
2 =>
array (size=2)
'id' => int 3
'primary' => boolean false
3 =>
array (size=2)
'id' => int 4
'primary' => boolean true
4 =>
array (size=2)
'id' => int 5
'primary' => boolean false
5 =>
array (size=2)
'id' => int 6
'primary' => boolean false
When the array is generated, it is always ordered by id
, like the above. What I wish to do is to have usort()
promote the array element where primary
is TRUE
to be the first element. There will always only be one element where primary
is TRUE
.
I then wrote a simple comparison function to use with usort()
:
$data = array(
array('id' => 1, 'primary' => FALSE),
array('id' => 2, 'primary' => FALSE),
array('id' => 3, 'primary' => FALSE),
array('id' => 4, 'primary' => TRUE),
array('id' => 5, 'primary' => FALSE),
array('id' => 6, 'primary' => FALSE),
);
function sortArray($a, $b){
if($a['primary']){
return -1;
}elseif($b['primary']){
return 1;
}else{
return 0;
}
}
var_dump($data);
usort($data, 'sortArray');
var_dump($data);
While the element with primary = TRUE
is now promoted to the front, the rest of the elements are now sorted in reverse order and the element with id = 5
is out of place:
array (size=6)
0 =>
array (size=2)
'id' => int 4
'primary' => boolean true
1 =>
array (size=2)
'id' => int 5
'primary' => boolean false
2 =>
array (size=2)
'id' => int 6
'primary' => boolean false
3 =>
array (size=2)
'id' => int 3
'primary' => boolean false
4 =>
array (size=2)
'id' => int 2
'primary' => boolean false
5 =>
array (size=2)
'id' => int 1
'primary' => boolean false
I know I can compare the ids, if both elements have the primary
property as false:
function sortArray($a, $b){
if($a['primary']){
return -1;
}elseif($b['primary']){
return 1;
}else{
return $a['id'] > $b['id'];
}
}
But, why is usort
randomizing the order of my other elements? Is it possible to use usort()
to just promote elements and leave the rest of the array untouched?
Try this comparison function:
function sortArray($a, $b)
{
if($a['primary'])
{
$result = 1;
}
elseif($b['primary'])
{
$result = -1;
}
else
{
$result = ($a['id'] < $b['id']) ? -1 : 1;
}
return $result;
}
You can change $result = ($a['id'] < $b['id']) ? -1 : 1;
to $result = ($a['id'] < $b['id']) ? 1 : -1;
to sort in reverse order.
In your comparison function, return $a['id'] > $b['id']
will either return 0 or 1 (true or false), never -1. From the documentation:
"The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second."
The fastest comparison sort is O(N*log(N)), which is slower than linear time. For this reason, I recommend just iterating over the array (O(N), linear time) and moving the element with 'primary' set to true
to the front of the array.