2

I want to rank the keys of an associative array in based upon their values. (top to down as 1, 2, 3....). Keys having same value will have same rank.

Here function getRanks() is meant to return an array containing keys and the ranks (number).

I expect it to return like this (this is sorted value wise in descending)

Array
        (
            [b] => 1
            [a] => 2
            [d] => 3
            [c] => 3
            [e] => 4
        )

There is issue in assigning the ranks (values) in the $ranks array which is to be returned.

What am I doing wrong? Do these loops even do something?


Code:

$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);

print_r(getRanks($json)); 

function getRanks($json) {
    $tmp_arr = json_decode($json, TRUE);
    $ranks = array();

    uasort($tmp_arr, function($a, $b){
        return $a == $b ? 0 : $a > $b ? -1 : 1; //descending
    });

    $keys = array_keys($tmp_arr); //after sorting
    $ranks = array_fill_keys($keys, 0); //copy keys
    $ranks[$keys[0]] = 1; //first val => rank 1

//------- WORKS FINE UNTIL HERE ------------------



    // need to fix the ranks assignment
    for($i=1; $i<count($keys)-1; $i++) {
        for($j=$i; $j < count($keys)-1; $j++) {
            if($tmp_arr[$keys[$j]] == $tmp_arr[$keys[$j+1]]) {
                $rank[$keys[$j]] = $i;
            }
        }
     }

    return $ranks;
}
  • Possible duplicate of [How to sort an array of associative arrays by value of a given key in PHP?](https://stackoverflow.com/questions/1597736/how-to-sort-an-array-of-associative-arrays-by-value-of-a-given-key-in-php) – Anurag Srivastava May 18 '19 at 10:17
  • 1
    @AnuragSrivastava I've already sorted by value. I need to fill ranks according to these sorted values in `$ranks` array. The suggested duplicate is not my question. –  May 18 '19 at 10:19

3 Answers3

2

Your approach seems unnecessarily complicated. In my version I kept the json-related copying part of it but finished it off in a simpler way:

function getRanks($json) {
    $tmp_arr = json_decode($json, TRUE);
    asort($tmp_arr);. // sort ascending
    $i=0; $lv=null;$ranks = array();
   foreach ($tmp_arr as $k=>$v) {
     if ($v>$lv){ $i++; $lv=$v;}
     $ranks[$k]=$i;
   }
   return $ranks;
}

See the demo here: https://rextester.com/LTOA23372

In a slightly modified version you you can also do the ranking in a descending order, see here: https://rextester.com/HESQP10053

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
1

I've also tried with another approach. I think it may not be the good solution because of high memory & CPU time consumption.

For small arrays (in my case) it works fine.

(I've posted because it may be an answer)

It creates array of unique values and fetches ranks accordingly.

$test = array('a'=> 50, 'b'=>60, 'c'=>20, 'd'=>20, 'e'=>10);
$json = json_encode($test);

print_r(getRanks($json));

function getRanks($json) {
    $tmp_arr = json_decode($json, TRUE);
    arsort($tmp_arr);
    $uniq_vals = array_values(array_unique($tmp_arr)); // unique values indexed numerically from 0

    foreach ($tmp_arr as $k => $v) {
        $tmp_arr[$k] = array_search($v, $uniq_vals) + 1; //as rank will start with 1
    }
    return $tmp_arr;
}
-1

This is the simple thing that you can do it by using php array function check example given below.

<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
asort($fruits);
foreach ($fruits as $key => $val) {
    echo "$key = $val\n";
}
?>
Ronak Chauhan
  • 681
  • 1
  • 8
  • 22