数据列表间隔穿插带分页算法

3 篇文章 0 订阅

首先封装一个class InterlacePageHelper 编写两个方法:一个是计算当前页的数据结构(pageInterlace),一个是列表数据构建(dataInterlace)

 /**
  * 计算分页之间的穿插
  * 参数说明:第一个列表总长度、第二个列表总长度、页码、页数量、第一个列表穿插长度、第二个列表穿插长度
  */
  public static function pageInterlace($beforeCount, $afterCount, $page, $pageSize, $beforeNumber, $afterNumber)
  {
        if (ceil(($beforeCount + $afterCount) / $pageSize) < $page) {
            return false;
        }
        $step_number        = $beforeNumber + $afterNumber;
        $total_offset       = ($page - 1) * $pageSize;
        $total_current      = $page * $pageSize;
        $step_y             = $total_offset % $step_number;
        $total_y            = $total_current % $step_number;
        $step               = floor($total_offset / $step_number);
        $offset_before_step = $offset_after_step = $step;
        $before_start_bool  = false;
        $after_start_bool   = false;
        if ($step_y > $beforeNumber) {
            $after_start_bool   = true;
            $offset_before_step = $offset_before_step + 1;
            $offset_before      = $offset_before_step * $beforeNumber;
            $offset_after       = ($offset_after_step * $afterNumber) + ($step_y - $beforeNumber);
        } else {
            if ($step_y != $beforeNumber) {
                $before_start_bool = true;
            } else {
                $after_start_bool = true;
            }
            $offset_before = $offset_before_step * $beforeNumber + $step_y;
            $offset_after  = $offset_after_step * $afterNumber;
        }

        $total_step        = floor($total_current / $step_number);
        $limit_before_step = $limit_after_step = $total_step;
        if ($total_y > $beforeNumber) {
            $limit_before_step = $limit_before_step + 1;
            $limit_before      = $limit_before_step * $beforeNumber;
            $limit_after       = ($limit_after_step * $afterNumber) + ($total_y - $beforeNumber);
        } else {
            $limit_before = $limit_before_step * $beforeNumber + $total_y;
            $limit_after  = $limit_after_step * $afterNumber;
        }
        $limit_before = $limit_before - $offset_before;
        $limit_after  = $limit_after - $offset_after;

        $before_start_number = 0;
        $after_start_number  = 0;

        if ($before_start_bool) {
            $before_start_number = $beforeNumber - $step_y;
        }
        if ($after_start_bool) {
            $after_start_number = $afterNumber - ($step_y - $beforeNumber);
        }
        if (!$before_start_bool && !$after_start_bool) {
            $before_start_bool = true;
        }
        if ($beforeCount < $offset_before && $afterCount < $offset_after) {
            $offset_before = $beforeCount;
            $offset_after  = $afterCount;
            $limit_before  = 0;
            $limit_after   = 0;
        } elseif ($beforeCount < $offset_before && ($afterCount > $offset_after && $afterCount < $offset_after + $limit_after)) {
            $offset_before = $beforeCount;
            $offset_after  = $total_offset - $offset_before;
            $limit_before  = 0;
            $limit_after   = $pageSize;
        } elseif ($beforeCount < $offset_before && $afterCount > $offset_after + $limit_after) {
            $offset_before = $beforeCount;
            $offset_after  = $total_offset - $offset_before;
            $limit_before  = 0;
            $limit_after   = $pageSize;
        } elseif (($beforeCount > $offset_before && $beforeCount < $offset_before + $limit_before) && $afterCount < $offset_after) {
            $offset_before = $total_offset - $offset_after;
            $offset_after  = $afterCount;
            $limit_before  = $pageSize;
            $limit_after   = 0;
        } elseif (($beforeCount > $offset_before && $beforeCount < $offset_before + $limit_before) && ($afterCount > $offset_after && $afterCount < $offset_after + $limit_after)) {
            $limit_before = $beforeCount - $offset_before;
            $limit_after  = $afterCount - $offset_after;
        } elseif (($beforeCount > $offset_before && $beforeCount < $offset_before + $limit_before) && $afterCount > $offset_after + $limit_after) {
            $limit_before = $beforeCount - $offset_before;
            $limit_after  = $pageSize - $limit_before;
        } elseif ($beforeCount > $offset_before + $limit_before && $afterCount < $offset_after) {
            $offset_before = $total_offset - $offset_after;
            $offset_after  = $afterCount;
            $limit_before  = $pageSize;
            $limit_after   = 0;
        } elseif ($beforeCount > $offset_before + $limit_before && ($afterCount > $offset_after && $afterCount < $offset_after + $limit_after)) {
            $limit_after  = $afterCount - $offset_after;
            $limit_before = $pageSize - $limit_after;
        }
        if ($limit_before == 0) {
            $after_start_bool   = true;
            $after_start_number = $limit_after;
        }
        if ($limit_after == 0) {
            $before_start_bool   = true;
            $before_start_number = $limit_before;
        }

        return [
            'page'                => $page,
            'pageSize'            => $pageSize,
            'step_before'         => $beforeNumber,
            'step_after'          => $afterNumber,
            'offset_before'       => $offset_before,
            'offset_after'        => $offset_after,
            'limit_before'        => $limit_before,
            'limit_after'         => $limit_after,
            'before_start_bool'   => $before_start_bool,
            'after_start_bool'    => $after_start_bool,
            'before_start_number' => $before_start_number,
            'after_start_number'  => $after_start_number,
        ];
    }

接着数据列表按照计算–数据按照穿插进去成为一个新的列表

/**
     * 数据按照穿插进去成为一个新的列表
     */
    public static function dataInterlace($beforeList, $afterList, $interlaceResult)
    {
        $new_list = [];
        //先看谁先开始--把头放进去
        $before_offset   = 0;
        $after_offset    = 0;
        $beforeListCount = count($beforeList);
        $afterListCount  = count($afterList);
        //虽然下面逻辑是处理好了--但是列表如果有空的还是处理一下
        if ($beforeListCount == 0 || $afterListCount == 0) {
            return $beforeListCount == 0 ? $afterList : $beforeList;
        }

        for ($i = 1; $i < $interlaceResult['pageSize']; $i++) {
            if ($before_offset + $after_offset >= $interlaceResult['pageSize'] || count($new_list) == ($beforeListCount + $afterListCount)) {
                break;
            }
            if ($i == 1) {
                if ($interlaceResult['before_start_bool']) {
                    $before_start_number = $interlaceResult['before_start_number'] == 0 ? $interlaceResult['step_before'] : $interlaceResult['before_start_number'];
                    $before_item         = array_slice($beforeList, $before_offset, $before_start_number);
                    $new_list            = array_merge($new_list, $before_item);
                    $before_offset       = $before_offset + $before_start_number;
                    $after_item          = array_slice($afterList, $after_offset, $interlaceResult['step_after']);
                    $new_list            = array_merge($new_list, $after_item);
                    $after_offset        = $after_offset + $interlaceResult['step_after'];
                }
                if ($interlaceResult['after_start_bool'] && $interlaceResult['after_start_number'] > 0) {
                    $after_item   = array_slice($afterList, $after_offset, $interlaceResult['after_start_number']);
                    $new_list     = array_merge($new_list, $after_item);
                    $after_offset = $after_offset + $interlaceResult['after_start_number'];
                }
                continue;
            }
            if ($before_offset < $beforeListCount) {
                $before_item   = array_slice($beforeList, $before_offset, $interlaceResult['step_before']);
                $new_list      = array_merge($new_list, $before_item);
                $before_offset = $before_offset + $interlaceResult['step_before'];
            }
            if ($after_offset < $afterListCount) {
                $after_item   = array_slice($afterList, $after_offset, $interlaceResult['step_after']);
                $new_list     = array_merge($new_list, $after_item);
                $after_offset = $after_offset + $interlaceResult['step_after'];
            }
        }

        return $new_list;
    }

示例:
这里我使用的是Yii2.0框架,调用示例:

//获取两个列表穿插数据的总数
$before_count = $before_query->count();
$after_count = $after_query->count();
//参数说明:第一个列表总长度、第二个列表总长度、页码、页数量、第一个列表穿插长度、第二个列表穿插长度
$interlace_result = InterlacePageHelper::pageInterlace($before_count, $after_count,$this->searchParams['page'], $this->searchParams['pageSize'], 3, 3);
$before_list = $before_query->offset($interlace_result['offset_before'])
 ->limit($interlace_result['limit_before'])
  ->orderBy('last_active_date desc,rl.id asc')
  ->asArray()
  ->all();
$after_list  = $after_query->offset($interlace_result['offset_after'])
   ->limit($interlace_result['limit_after'])
   ->orderBy('last_active_date desc,rl.id asc')
   ->asArray()
   ->all();
 $list        = InterlacePageHelper::dataInterlace($before_list, $after_list, $interlace_result);
//获取到当前页的列表数据
return  $list;
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值