SO,
The problem
I have an issue with custom array sorting. I have an array:
$rgData = [
3 => 1,
5 => 0,
1 => 2,
9 => 0,
0 => 1,
4 => 2,
2 => 1,
7 => 0,
6 => 0,
8 => 0,
];
-it contain keys with their counts (actually, it came after some operations with array_count_values
). Now I want to sort it that:
asort()
)For sample above result should be:
[5=>0, 6=>0, 7=>0, 8=>0, 9=>0, 0=>1, 2=>1, 3=>1, 1=>2, 4=>2]
My approach
I have no idea how to resolve this with sort by user-defined since usort
or uasort
accept only values for comparing while uksort
- only keys and I need both of them in my comparison function. The only way that I have now - is to do this:
$rgData = ['3'=>1, '5'=>0, '1'=>2, '9'=>0, '0'=>1, '4'=>2, '2'=>1, '7'=>0, '6'=>0, '8'=>0];
$rgTemp = [];
asort($rgData);
$i = 0;
$mPrev = current($rgData);
foreach($rgData as $mKey=>$mValue)
{
$rgTemp[$mPrev==$mValue?$i:++$i][$mKey] = $mValue;
$mPrev = $mValue;
}
$rgTemp = array_map(function($rgX)
{
ksort($rgX);
return $rgX;
}, $rgTemp);
$rgData = [];
//can't use call_user_func_array('array_merge', $rgTemp) - it spoils numeric keys
foreach($rgTemp as $rgX)
{
foreach($rgX as $mKey=>$mValue)
{
$rgData[$mKey] = $mValue;
}
}
//var_dump($rgData);
-i.e. split array by values first, then do the stuff.
The question
How to do this in more easy way? I used asort
+ cycled ksort
via array_map
with final gathering loop. Temp array also used. It looks weird. I hope simpler method exists.
This should do what you want. It sorts by the keys, but we can access the value inside the function, so we can use that as our sort criteria too.
uksort($rgData, function($a, $b) use($rgData){
$aVal = $rgData[$a];
$bVal = $rgData[$b];
// Compare the values
if($aVal === $bVal){
// If they are the same, compare the keys
return $a - $b;
}
// Otherwise compare the values
return $aVal - $bVal;
});