《手动推荐》加《自动推荐》商品,如何分页问题

如题,我先描述下业务场景:
  我司 APP 有个营销版块,以瀑布流的形式展示商品。展示的商品分为二种数据:一是手动指定的商品,数量少且不固定,大概 0~30 之间浮动;二是自动推荐的商品,通过简单的筛选展示,比如精选、热卖之类的。
  手动指定商品需要优先展示,比如说手动指定了 5 个商品,并且瀑布流一页仅展示 10 个商品,那么第 1 页瀑布流,前面 5 个就是手动指定,往后全是自动推荐的商品,包括后面的分页,全部都是自动推荐的商品。同理,如果手动指定了 15 个商品,那么第 1 页的所有商品,和第 2 页前面 5 个商品都是手动指定的,往后才是自动推荐的。

我尝试写了一个方法,想让大家看看,还有什么可以优化的地方,或者更好的写法

/**
 * @param int $page 瀑布流的页码
 * @param int $pageSize 每页展示数量
 * @param int $manualQuantity 手动推荐的数量
 * @return array
 */
function page_offset(int $page, int $pageSize, int $manualQuantity)
{
    //手动推荐的余数
    $manualRemainder = $manualQuantity % $pageSize;

    //手动推荐的总页数
    $manualPageCount = floor($manualQuantity / $pageSize) + 1;

    //自动推荐分页的 offset 和 limit
    $offset = max(0, ($page - $manualPageCount) * $pageSize - $manualRemainder);
    $limit = $offset ? $pageSize : max(0, ($page * $pageSize) - $manualQuantity);

    return [$offset, $limit];
}

echo implode(PHP_EOL, [
        implode("\t", page_offset(1, 10, 0)), //   0 10
        implode("\t", page_offset(2, 10, 0)), //  10 10
        implode("\t", page_offset(3, 10, 0)), //  20 10
        implode("\t", page_offset(1, 10, 3)), //   0  7
        implode("\t", page_offset(2, 10, 3)), //   7 10
        implode("\t", page_offset(3, 10, 3)), //  17 10
        implode("\t", page_offset(1, 10, 14)),//   0  0
        implode("\t", page_offset(2, 10, 14)), //  0  6
        implode("\t", page_offset(3, 10, 14)), //  6 10
    ]) . PHP_EOL;
讨论数量: 11

为什么不从数据库设计考虑?多字段权重排序的事情

1年前 评论
浮心 (楼主) 1年前
decade_decade_decade 10个月前
浮心 (楼主) 10个月前
decade_decade_decade 10个月前

这段代码主要是根据页面、每页展示数量和手动推荐数量计算出分页的 offset 和 limit,并返回一个包含这两个值的数组。

为了优化这段代码,可以考虑以下几点:

可以使用三元运算符来代替一些条件语句,使代码更简洁。
可以将一些重复的运算提取出来,避免重复计算。
可以使用更具有可读性的变量名。

下面是优化后的代码:

/**

@param int $page 瀑布流的页码

@param int $pageSize 每页展示数量

@param int $manualQuantity 手动推荐的数量

@return array
*/
function page_offset(int $page, int $pageSize, int $manualQuantity)
{
// 计算手动推荐的总页数和余数
manualPageCount=ceil(manualPageCount=ceil(manualQuantity / $pageSize);
$manualRemainder = $manualQuantity % $pageSize;

// 计算自动推荐的总数和所在页码
$autoQuantity = max(0, manualQuantity−(manualQuantity−(page - 1) * $pageSize);
$autoPage = $page - $manualPageCount;

// 计算offset和limit
$offset = max(0, $autoPage * $pageSize + $manualRemainder);
$limit = autoQuantity>0?min(autoQuantity>0?min(autoQuantity, $pageSize) : 0;

return [$offset, $limit];
}

echo implode(PHP_EOL, [ implode("\t", page_offset(1, 10, 0)), implode("\t", page_offset(2, 10, 0)), implode("\t", page_offset(3, 10, 0)), implode("\t", page_offset(1, 10, 3)), implode("\t", page_offset(2, 10, 3)), implode("\t", page_offset(3, 10, 3)), implode("\t", page_offset(1, 10, 14)), implode("\t", page_offset(2, 10, 14)), implode("\t", page_offset(3, 10, 14)), ]) . PHP_EOL;

优化后的代码使用了更清晰的变量名,将手动推荐的总页数和余数的计算提前,并且使用了三元运算符来代替一些条件语句。同时,通过计算自动推荐的总数和所在页码,避免了重复计算,使代码更加高效。

11个月前 评论
浮心 (楼主) 10个月前
xrxb 10个月前
浮心 (楼主) 10个月前
/**
 * 计算瀑布流分页中自动推荐分页的offset和limit
 * @param int $page 瀑布流的页码
 * @param int $pageSize 每页展示数量
 * @param array $manualIds 手动推荐的ID列表
 * @return array 包含offset和limit的数组
 * @throws InvalidArgumentException 如果页码、每页数量或手动ID列表参数不合法,则抛出InvalidArgumentException异常
 */
function page_offset(int $page, int $pageSize, array $manualIds = []) {
    // 输入数据有效性判断
    if($page <= 0 || $pageSize <= 0 || empty($manualIds)) {
        throw new InvalidArgumentException('Invalid input parameters');
    }

    $manualQuantity = count($manualIds);

    // 将手动推荐数量拆分成更小的单位
    $manualChunks = array_chunk($manualIds, $pageSize);
    $manualPageCount = count($manualChunks);

    // 计算offset和limit
    $offset = max(0, ($page - $manualPageCount) * $pageSize - $manualQuantity % $pageSize);
    $limit = $offset ? $pageSize : max(0, ($page * $pageSize) - $manualQuantity);

    return [$offset, $limit];
}

// 测试样例
try {
    $manualIds = [1, 2, 3, 4, 5, 6, 7];
    echo implode(PHP_EOL, [
        implode("\t", page_offset(1, 10)),           // 抛出InvalidArgumentException异常
        implode("\t", page_offset(1, 10, [])),       // 抛出InvalidArgumentException异常
        implode("\t", page_offset(-1, 10, $manualIds)), // 抛出InvalidArgumentException异常
        implode("\t", page_offset(1, 0, $manualIds)),  // 抛出InvalidArgumentException异常
        implode("\t", page_offset(1, 10, $manualIds)), //  0 10
        implode("\t", page_offset(2, 10, $manualIds)), // 10  0
    ]) . PHP_EOL;
} catch (InvalidArgumentException $e) {
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
}
10个月前 评论
浮心 (楼主) 10个月前

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