【问题标题】:Properly sorting multidimensional array using usort and spaceship operator使用 usort 和 spaceship 运算符正确排序多维数组
【发布时间】:2017-11-02 17:21:31
【问题描述】:

我需要使用以下逻辑对以下数组进行排序:如果“分数”相同,我想使用“时间”进行比较。数组如下:

$user_scores = [ 82 => [ 'score' => 1, 'time' => 6.442 ],
                 34 => [ 'score' => 1, 'time' => 5.646 ],
                 66 => [ 'score' => 3, 'time' => 1.554 ]
               ]

上述数组中的“键”是“user_ids”,我需要将其保存在排序后的数组中。到目前为止,我最好的尝试如下 -

$result = usort( $user_scores, function ( $a, $b ) {
    if ( $a['score'] == $b['score'] ) {
        return $a['time'] == $b['time'];
        }
    return $a['score'] <=> $b['score'];
} );

显然,这不起作用,我得到 $user_scores 数组,其中所有键都替换为 0、1、2 而不是 user_ids(82、34 和 66)。排序也不起作用。

对于上面的数组,我想要的输出是 $user_scores 数组:

$user_scores = [ 34 => [ 'score' => 1, 'time' => 5.646 ],
                 82 => [ 'score' => 1, 'time' => 6.442 ],
                 66 => [ 'score' => 3, 'time' => 1.554 ]
               ]

如果您能告诉我如何使用 spaceship 运算符来完成这项工作(如果有意义的话),我将不胜感激。感谢您抽出宝贵时间,期待您的回复。

---更新---

需要的排序逻辑是这样的:

  1. 分数越高,排名越高。
  2. 时间越高,等级越低。

它基本上是对测验的结果进行排序。时间最少的得分最高的人将在榜首;而那些分数较低且时间较长的人将排在最后。

【问题讨论】:

    标签: php sorting multidimensional-array usort asort


    【解决方案1】:

    要保留密钥,您只需要使用uasort()

    我建议宇宙飞船操作员进行 3 路比较(PHP7 及更高版本可用)。

    您的代码中的$result 只会返回true/false,所以这对您没有用。 sort()'ing 函数不能分配给变量;他们直接修改输入数组。

    当向飞船操作员提供数组数据时,将比较前两个元素。如果有差异,则返回1-1。如果存在平局(比较评估为0,则将评估接下来的两个元素。此行为将持续到发生非零评估或没有更多元素要迭代。这是一个相当干净/可读的语法实施。

    要按降序排序,请将$b 值写在左边,$a 值写在右边。

    代码:(Demo)

    $user_scores = [
        82 => ['score' => 1, 'time' => 6.442],
        34 => ['score' => 1, 'time' => 5.646],
        66 => ['score' => 3, 'time' => 1.554],
        7  => ['score' => 2, 'time' => 4.442],
        99 => ['score' => 4, 'time' => 3.646],
        55 => ['score' => 1, 'time' => 2.554]
    ];
    
    uasort($user_scores, function($a, $b) {
        return [$b['score'], $a['time']] <=> [$a['score'], $b['time']];
    });
    var_export($user_scores);
    

    输出:

    array (
      99 => 
      array (
        'score' => 4,
        'time' => 3.646,
      ),
      66 => 
      array (
        'score' => 3,
        'time' => 1.554,
      ),
      7 => 
      array (
        'score' => 2,
        'time' => 4.442,
      ),
      55 => 
      array (
        'score' => 1,
        'time' => 2.554,
      ),
      34 => 
      array (
        'score' => 1,
        'time' => 5.646,
      ),
      82 => 
      array (
        'score' => 1,
        'time' => 6.442,
      ),
    )
    

    【讨论】:

    • 时间键在输出中发生变化意味着时间 = 5.646 到 5.64599999999999990762944435118697583675384521484375
    • @BunkerBoy 在 PHP7 中没问题:sandbox.onlinephpfunctions.com/code/… 我总是在发布之前进行测试,但请好好检查一下。我宁愿有人给我一个糟糕的答案,也不愿我在 SO 上扔坏代码。谢谢。
    • 好的,我在发布问题时搞砸了很多时间。分数需要递减(更大的得分者应该在顶部)并且时间需要递增(更大的时间应该在最后)。真的很抱歉弄得一团糟。
    • 太棒了!如果我理解正确,请告诉我:首先,我们检查被比较的两个分数是否相等;如果是,我们进行时间比较。否则,我们只需比较分数并对数组进行排序。
    • @TheBigK 我只是想让你知道我已经完善了我的旧答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多