前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP 实现分类数据间隔排序

PHP 实现分类数据间隔排序

原创
作者头像
lascyb
修改2021-11-18 11:44:06
1K0
修改2021-11-18 11:44:06
举报
文章被收录于专栏:PHP-轮子制造机PHP-轮子制造机

数据场景:

现有视频若干,各视频有所属分类,数据项 格式如下

代码语言:txt
复制
[
    "id"=>1,
    "cate_id"=>1    
]

现有视频已按照指定规则排序完成

排序要求:

顺序排列中,连续的10个视频中,不能有属于相同分类的视频

生成假数据:

代码语言:javascript
复制
//假设有100个分类,ID为 1-100  //$cates=[1,...,100];
//生成5000条视频数据
$video=[];
for ($i=1;$i<=5000;$i++){
    $video[]=[
        "id"=>$i,
        "cate_id"=>mt_rand(1,100), //所属分类ID
        "other"=>$i
    ];
}

代码实现:

代码语言:javascript
复制
function buildQueue($list=[],$step=10){
    $data=[]; //接收生成的数据
    $steps=[]; /**接收 因 前后10步长范围有相同分类导致无法插入的数据项,
        存储格式为:
        $steps = [
            "cate_id"=>[
                "wait"=>0-10 //需等待步长
                "queue"=>[] //存储数据项
            ],
            ....
        ]
        */
        
    //遍历$list插入$data数组 ,如果当前项前后10步长有相同分类元素,则追加进$steps数组
    foreach ($list as $item){ 
        if (isset($steps[$item["cate_id"]]["wait"])&&$steps[$item["cate_id"]]["wait"]>0){
             //需等待步长耗尽
            //dump("加入等待队列");
            if (isset($steps[$item["cate_id"]]["queue"])){ //队列已存在
                array_unshift($steps[$item["cate_id"]]["queue"],$item); //从头部追入数据,先进先出
            }else{ //队列不存在
                $steps[$item["cate_id"]]["queue"]=[$item]; //初始化队列
            }
        }else{ //无需等待步长
            $steps[$item["cate_id"]]["wait"]=$step; //记录插入后在$steps中记录需等待步长10
            $data[]=$item; //直接追加进$data数组
            reduceSteps($steps,$data,$step); //操作$steps数组-为在等待的数据减去等待步长1
        }
    }
    //debug start 打印$data中已保存的数据
    //$i=1;
    //foreach ($data as $datum){
    //    dump($i++.": ".$datum["id"].'-'.$datum["cate_id"]);
    //}
    
    //dump($steps); //$steps数组可能不为空,因为步长间距不足10
    //debug end
    
    //步长间距从10缩减到0,确保$steps清空,$list数据不丢失
    for ($step-=1;$step>=0;$step--){
        //dump("step:----------".$step);
        //$num1=count($data)-1;
        reduceSteps($steps,$data,$step);
        //$num2=count($data)-1;
        //for ($i=$num1;$i<=$num2;$i++){ //打印$data中本次追加的数据
        //    dump(($i+1).": ".$data[$i]["rate"].'-'.$data[$i]["id"].'-'.$data[$i]["cate_id"]);
        //}
    }
    //dump($steps); 是否清空
    return $data;
}
//$steps与$data使用引用类型,降低内存使用量,降低代码复杂度
function reduceSteps(&$steps,&$data,$step=10){
        //为所有在等待的数据减去等待步长1
        foreach ($steps as $key=>$datum){ //
            if ($datum["wait"]>0){
                $steps[$key]["wait"]--;
            }
        }
        //处理在等待数据
        foreach ($steps as $key=>$datum){
            if ($datum["wait"] == 0){ //无需等待的数据
                if (!empty($steps[$key]["queue"])){ //等待队列不为空
                    $data[]=array_pop($steps[$key]["queue"]); //弹栈,最先等待的数据最先弹出
                    $steps[$key]["wait"] = $step; //此cate_id分类继续等待步长
                    reduceSteps($steps,$data,$step); ////为所有在等待的数据减去等待步长1
                }else{ //等待队列为空
                    unset($steps[$key]); //删除cate_id索引相关数据
                } 
                //没有等待步长为0的数据,则跳出
            }
        }

    }

代码测试:

代码语言:javascript
复制
dump(microtime(true));
$data=buildQueue($video);
dump(microtime(true));
foreach ($data as $datum) {
    dump($datum["id"]."-".$datum["cate_id"]."-".$datum["other"]);
}

测试结果:(因cate_id随机生成,所以测试结果可能不同)

代码语言:javascript
复制
1637206150.3998
1637206150.4236
"1-77-1"
"2-85-2"
"3-25-3"
"4-94-4"
"5-22-5"
"6-61-6"
"7-66-7"        // -- id:7   -  所属分类66
"8-56-8"        // -- id:8    -    所属分类56
"10-51-10"
"11-27-11"
"12-8-12"
"13-100-13"
"14-65-14"
"16-52-16"
"17-11-17"
"18-91-18"
"9-66-9"       // -- id:9    -    所属分类66   - 距离同分类 ID 7 步长10
"15-56-15"     // -- id:15    -    所属分类56  - 距离同分类 ID 8 步长10
"19-55-19" 
"20-43-20"
"21-46-21"
"22-50-22"
...

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据场景:
  • 排序要求:
  • 生成假数据:
  • 代码实现:
  • 代码测试:
  • 测试结果:(因cate_id随机生成,所以测试结果可能不同)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档