【问题标题】:Returning An Array Key Based On A Integer返回基于整数的数组键
【发布时间】:2013-11-22 01:46:38
【问题描述】:

我正在为每个用户存储一个分数。每个分数都应该映射到一个等级。例如,得分为 17 的人将被评为 blogger,因为 blogger 的得分要求为 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'),
)

因为在这种情况下,分数是 17,所以应该返回 $rank[15]。因为 $score 大于或等于 15。我该怎么办?

编辑:

Uksort 使用用户定义的比较函数按键对数组进行排序。我不确定它在内部是如何工作的。在下面的函数中,$a 是什么,$b 是什么?

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

uksort($rank, "cmp");

编辑:我注意到我的问题含糊不清,我很抱歉,因为 iut 是凌晨 3 点,而且我没有像往常那样清晰地思考。谢谢大家的回复。我必须考虑重新表述这个问题。

接受的答案

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))];
}

【问题讨论】:

标签: php sorting ranking


【解决方案1】:

可能是答案?根据您的问题:

$score = 17;

$ranks = 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')
);

foreach($ranks as $rank)
{
    if($score >= $rank )
    {
        echo $rank['profile_rank_name']."-".$rank['profile_rank_image'];
    }
}

【讨论】:

  • 谢谢你,这是我第一次解决这个问题的方式。我将数组中的排名存储在数据库表中,并通过连接和比较来获取排名。现在这是在 PHP 中重写 SQL 功能以消除 JOIN 以获得更好性能的努力。
  • 没问题,你可能是第一次编写这么简单的程序:D
【解决方案2】:

1) 对数组进行排序,使排名按升序排列(如果未排序,则下一个将失败)

2) 你需要循环你的键而不是数组内容,所以首先获取键

$keys = array_keys($ranks)

3) 使用 foreach 或 for 两者中的任何一个来循环数组

foreach($keys as $key){
   if($score >= $key){
       echo $ranks[$key];
   }
}

注意:如果上面的代码运行时没有排序,你会得到错误的结果,如果有大约 1000 个等级,一个有效的方法是使用二进制搜索来获得 $score 在 $ranks 中的粗略位置

【讨论】:

    【解决方案3】:

    试试这样的

    <?php
        $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'),
    );
    
    
    foreach ($rank as $k=>$v)
    {
        if($score<=$rank[$k])
        {
            print_r($v);//Prints the first array element.
            break; 
        }
    }
    

    输出:

    Array ( [profile_rank_name] => Blogger [profile_rank_image] => blogger.png )
    

    【讨论】:

      【解决方案4】:

      遍历你的数组,如果值小于或等于它们的分数,则为数组中的项目设置一个变量。当值更大时中断。

      我已经 10 多年没有写过 php 了,但是类似:

      foreach($rank as $currentRank=>$rankData){
          if($currentRank <= $score) $matchedRank = $rankData;
          else break;
      }
      

      【讨论】:

      • 如果数组未排序则不起作用。例如,如果您有两个键 15 et 161516 之前,您的代码将返回 15 并中断循环。而不是返回良好的价值16
      • 我假设它是根据问题的措辞进行排序的。我不确定你的例子是否有意义。对 16 之前的 15 进行排序,如果他们的分数为 16 或更高,则返回 16。
      • 如果$score = 14 会发生什么?
      • 那么 $matchedRank 将为空。我不相信这是问题的一部分。 14分的时候你知道作者想做什么吗?
      • 这不是问题以及关键排序问题,但为了防止出现故障,我们必须做出所有假设......:P
      【解决方案5】:
      $keys = array_keys($rank);
      sort($keys); // not needed in your example, just to be *bug* free
      $score = 17;
      $index = array_reduce($keys, function ($prev, $next) use ($score) {
          return ($prev <= $score && $score < $next) ? $prev : $next;
      }) ?: min($keys);
      var_dump($index); // int(15)
      print $rank[$index]['profile_rank_name']; // Blogger
      

      如果$score 小于最小键,$index 将是最小数组键。 所以它适用于$score &lt; min($keys)$score &gt; max($keys)。 :)

      工作演示:https://eval.in/65190

      $scorerange(0, 100) 的演示:https://eval.in/65196

      PS:PHP 5.3+(我使用的是短三元和闭包回调)

      【讨论】:

      • 也许这是 php 的 SOP,但我猜它太花哨了。 :-) 顺便说一句,这种问题的解决方案在 C# 中很漂亮。 array.Where(item => item.Key item.Key)
      • 如果 sort() 函数不能通过引用工作,那将是单行的。 ;/ 我同意这可能太花哨了,但无论如何,它不如公认的答案那么花哨......
      • PS:downvoter 应该说我在闭包中使用了错误的变量名,而不是仅仅 downvoting,因为尽管问题已经解决,但它是一个完整的答案。
      • 我对你投了赞成票,保罗,这段代码值得称赞,谢谢你发帖
      • @MichaelRich 谢谢!在您投票之后,有人无缘无故地拒绝了我的回答,但无论如何,没关系...... :)
      【解决方案6】:

      这正是你想要的;)

      $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);
      

      输出

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

      【讨论】:

      • 必须解决$score &lt; min($keys) 方案。 :)
      • 这实际上工作得很好,在使用它之前我会尽力理解这段代码。谢谢你的回答:) $score
      • 如有任何问题,请发表评论;)!
      猜你喜欢
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      相关资源
      最近更新 更多