3

I want to sort an associative array and there is an inbuilt function to achieve the same viz. arsort(), but the problem with this function is that it doesn't maintain the original key order when values are same. e.g.

$l = [
    'a' => 1,
    'b' => 2,
    'c' => 2,
    'd' => 4,
    'e' => 5,
    'f' => 5
];

The result which I want is :

$l = [
    'e' => 5,
    'f' => 5,
    'd' => 4,
    'b' => 2,
    'c' => 2,
    'a' => 1
];

arsort() gives the result in descending order but it randomly arranges the element when values are same. This question is not a duplicate of PHP array multiple sort - by value then by key?. In that question it is asking for same numeric value to be sorted alphabetically but in my question I am asking values to sorted according to the original order if they are same.

Community
  • 1
  • 1
iit2011081
  • 742
  • 8
  • 26
  • http://php.net/manual/en/function.array-multisort.php or http://php.net/manual/en/function.usort.php – E_p Jul 18 '16 at 22:07
  • I can't reproduce this. for your example, I get the results you are wanting (e,f,d,b,c,a) with arsort – Jeff Puckett Jul 18 '16 at 22:09
  • Definitely reproducible https://3v4l.org/kqZLd – rjdown Jul 18 '16 at 22:11
  • I am getting e,f,d,c,b,a but it is not random for me, I tried refreshing many times. Probably we need to write a custom function if that is the case and you are particular about the keys to use in a specific order. – Dharam Jul 18 '16 at 22:43
  • Possible duplicate of [PHP array multiple sort - by value then by key?](http://stackoverflow.com/questions/2282013/php-array-multiple-sort-by-value-then-by-key) – Don't Panic Jul 18 '16 at 23:08
  • @dont-panic This question is slightly different from the one which you provided. In that question it is asking for same numeric value to be sorted alphabetically but in my question I am asking values to sorted according to the original order if they are same. – iit2011081 Jul 19 '16 at 04:15
  • @jeff-puckett-ii Please use this array. $l = [ 'a' => 1, 'b' => 2, 'c' => 2, 'd' => 4, 'g' => 5, 'e' => 5, 'f' => 5 ]; The result which I want is g, e, f, d, b, c, a . – iit2011081 Jul 19 '16 at 04:38
  • Yes, I agree that that's different. Sorry I overlooked the difference initially. – Don't Panic Jul 19 '16 at 23:27

2 Answers2

4

There is probably a more efficient way to do this, but I think this should work to maintain the original key order within groups of the same value. I'll start with this array for example:

$l = [ 'a' => 1, 'b' => 2, 'c' => 2, 'd' => 4, 'g' => 5, 'e' => 5, 'f' => 5 ]; 
  1. Group the array by value:

    foreach ($l as $k => $v) {
        $groups[$v][] = $k;
    }
    

    Because the foreach loop reads the array sequentially, the keys will be inserted in their respective groups in the correct order, and this will yield:

    [1 => ['a'], 2 => ['b', 'c'], 4 => ['d'], 5 => ['g', 'e', 'f'] ];
    
  2. sort the groups in descending order by key:

    krsort($groups);
    
  3. Reassemble the sorted array from the grouped array with a nested loop:

    foreach ($groups as $value => $group) {
        foreach ($group as $key) {
            $sorted[$key] = $value;
        }
    }
    
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
1

You can use array_multisort. The function can be a bit confusing, and really hard to explain, but it orders multiple arrays, and the first array provided gets sorted based on the order of subsequent arrays.

Try:

array_multisort($l, SORT_DESC, array_keys($l));

See the example here: https://3v4l.org/oV8Od

It sorts the array by values descending, then is updated by the sort on the keys of the array.

Scopey
  • 6,269
  • 1
  • 22
  • 34
  • It is not working as expected for the array $l = [ 'a' => 1, 'b' => 2, 'c' => 2, 'd' => 4, 'g' => 5, 'e' => 5, 'f' => 5 ]; I want the answer to be g, e, f, d, b, c, a but it is giving me e, f, g, d, b, c, a. – iit2011081 Jul 19 '16 at 04:22
  • In that case, you have custom logic ('g' is usually after 'e' and 'g'), so you'll need to implement some custom sorting algorthm – Scopey Jul 19 '16 at 05:04
  • Could you please help me in writing that logic. My problem statement is simple that if value are same then they follow the same order as the original array. – iit2011081 Jul 19 '16 at 05:10
  • it's not custom logic, it just that the order should be by value, not by key – Federico Schiocchet Jan 22 '21 at 16:32