Search code examples
phpsortingranking

Returning An Array Key Based On A Integer


I am storing a score for each of my users. Each score should be mapped to a rank. E.g., someone with a score of 17 would be ranked blogger because blogger has a score requirement of 15.

$score = 17;

$rank = array(
    15 => array('profile_rank_name' => 'Blogger', 'profile_rank_image' => 'blogger.png'),
    18 => array('profile_rank_name' => 'News Editor', 'profile_rank_image' => 'news_editor.png'),
    23 => array('profile_rank_name' => 'Researcher', 'profile_rank_image' => 'researcher.png'),
    29 => array('profile_rank_name' => 'Publications Assistant', 'profile_rank_image' => 'publications_assistant.png'),
    36 => array('profile_rank_name' => 'Editorial Assistant', 'profile_rank_image' => 'editorial_assistant.png'),
    45 => array('profile_rank_name' => 'Copy Editor', 'profile_rank_image' => 'copy_editor.png'),
)

Because, in this instance, score is 17 then $rank[15] should be returned. Because $score is greater or equal than 15. How could I go about this?

Edit:

Uksort sorts an array by keys using a user-defined comparison function. I'm not sure how it's working internally. In the below function what is $a and what is $b?

if( ! function_exists('cmp'))
{
    function cmp($a, $b)
    {
        return $a;
    }
}

uksort($rank, "cmp");

Edit: I notice the ambiguity in my question, I apologies as iut's 3am and I'm not thinking as clearly as I would normally. Thank you all for replies. I must think of rephrasing the question.

Accepted Answer

public function get_profile_rank($score)
{
    /* This method exists as an optimisation effort. Ranks are defined within the database table `author_profile_rank`.
     * When we don't need application functionality on ranks and we only need to display the rank name and image we
     * call this method. It saves using a table join to retrieve the rank name and image.
     * http://stackoverflow.com/questions/19886351/returning-an-array-key-based-on-a-integer/19886467?noredirect=1#comment29583797_19886467
     */

    if($score <= 17)
    {
        return array('profile_rank_name' => 'Blogger', 'profile_rank_image' => 'blogger.png');
    }
    elseif($score >= 45)
    {
        return array('profile_rank_name' => 'Copy Editor', 'profile_rank_image' => 'copy_editor.png');
    }

    $ranks = array(
        23 => array('profile_rank_name' => 'Researcher', 'profile_rank_image' => 'researcher.png'),
        29 => array('profile_rank_name' => 'Publications Assistant', 'profile_rank_image' => 'publications_assistant.png'),
        36 => array('profile_rank_name' => 'Editorial Assistant', 'profile_rank_image' => 'editorial_assistant.png'),
    );

    $lower = function($val) use ($score)
    {
        if($val <= $score) return TRUE;
    };

    return $ranks[max(array_filter(array_keys($ranks), $lower))];
}

Solution

  • This does exactly what you want ;)

    $score = 17;
    
    $rank = array(
        15 => array('profile_rank_name' => 'Blogger', 'profile_rank_image' => 'blogger.png'),
        18 => array('profile_rank_name' => 'News Editor', 'profile_rank_image' => 'news_editor.png'),
        23 => array('profile_rank_name' => 'Researcher', 'profile_rank_image' => 'researcher.png'),
        29 => array('profile_rank_name' => 'Publications Assistant', 'profile_rank_image' => 'publications_assistant.png'),
        36 => array('profile_rank_name' => 'Editorial Assistant', 'profile_rank_image' => 'editorial_assistant.png'),
        45 => array('profile_rank_name' => 'Copy Editor', 'profile_rank_image' => 'copy_editor.png'),
    );
    
    $keys = array_keys($rank);
    
    $lower = function ($val) use ($score){
        if($val <= $score) return true;
    };
    
    
     $key_res = array_filter($keys, $lower);
    
     $user_rank = $rank[max($key_res)];
    
     var_dump($user_rank);
    

    OUTPUT

    array (size=2)
      'profile_rank_name' => string 'Blogger' (length=7)
      'profile_rank_image' => string 'blogger.png' (length=11)