如何对百条/百万条答题数据进行排行榜排序?

请尝试在评论区里写下答案(如不能清楚表述,那么你可能没真正理解)。欢迎参与,为下一次求职做准备。

某厂面试题

有类似如下的数组,开始是100条

[
        [
            'id' => 1,
            'grade' => 100,
            'time' => 50
        ],
        [
            'id' => 2,
            'grade' => 90,
            'time' => 60
        ],
]

分数越高排名越高,分数相同时间越低排名越高
在不使用redis zset的情况下得出前十排行榜


而后延伸题,如果数据量达到了十万/百万或者更甚该如何处理得到排行榜

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 11
chowjiawei

数据插入到mysql的时候 插入redis bigmap bigmap资源可省了 然后根据bigmap的id去mysql直接查询

3年前 评论
laisxn

数量少,函数array_multisort()结合array_column(),排序完,取前十个

延申题,看使用场景,可以第一次可以使用简单yield,循环计算出符合排序的前二十个,并缓存,下一次产生新数据,只需要和这二十个比较,为什么是二十个,避免分数相同的情况要从源数据从新对比

简单回答,不保证对 :joy:

3年前 评论

100w 条的数组?

3年前 评论
Aroad (楼主) 3年前

用redis的string和list,手动维护一个有序的list

    $time = $redis->get('key:' . $grade)

    if ($time && $time < $new_time) {
        $redis->rPush('list:' . $grade, $id)
    } else {
        $redis->lPush('list:' . $grade, $id)
        // 记录更新当前分数时间
        $redis->set('key:' . $grade, $new_time)
    }

最后把100个list合并成一个list就好了。

3年前 评论

mysql 排序后期肯定会慢,如果可以的话用MongoDB 简单排序应该也是支持的,查出id 在去mysql 查也是一种方案呢

3年前 评论

laravel有个collect方法很好用 这个是并列排名的实现方法 可以参考一下

collect($data)
    ->groupBy('grade')
    ->sortKeysDesc(SORT_NUMERIC)
    ->values()
    ->each(function ($data, $key) {
        foreach ($data as $datum) {
            $datum['rank'] = $key + 1;
        }
    })
    ->toArray();
2年前 评论

目的是得出前十的排行榜,不是去排序这一百万数据,所以创建一个前十的数组,然后遍历一百万数据,大于数组中的最小值就插入到数组中

1年前 评论

我觉得可以使用类似插入排序的方式,比如只需要前10,那么超出第10的就放弃插入就可以。

1年前 评论

没那么多想法,我想的就2种
1、根据排行榜时效性需求 用数据库查出来 更新缓存ttl 减少数据库查询
2、空间换时间,单独一张排行榜表,在插入的时候,判断排行值
条件1,排行表不满足10条 插入当前数据
条件2、排行榜表满足10条,插入的数据排行值是否大于最小值
不大于 放弃 大于 删除最少值 插入当前数据
独立的10条数据表,怎样操作都无所谓了吧

10个月前 评论

可以用小頂堆算法获取前10排序,然后再通过函数排序

4个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!