在业务开发中,经常会遇到需要根据给定的天数阈值,查找对应百分比值的需求。比如用户连续签到天数达到3天给5%的奖励,7天给10%,15天给20%,这种阶梯式的规则匹配就属于典型的数组区间匹配场景。

基础场景:有序数组遍历匹配
如果阈值区间是递增且连续的,我们可以把阈值和对应的百分比存放在一个有序数组中,然后遍历数组找到第一个小于等于目标天数的阈值,返回对应的百分比。
数据结构定义
我们先定义阈值和百分比的对应关系数组,键为天数阈值,值为对应的百分比:
<?php
// 定义天数阈值和对应百分比的数组,键为天数,值为百分比
$thresholdMap = [
3 => 5,
7 => 10,
15 => 20,
30 => 30,
];
<?php
实现匹配函数
函数逻辑是从大到小遍历阈值,找到第一个小于等于目标天数的阈值,返回对应的百分比,如果目标天数小于最小阈值则返回默认值:
<?php
/**
* 根据天数阈值查找对应百分比值
* @param int $days 目标天数
* @param array $thresholdMap 阈值映射数组,键为天数,值为百分比
* @param int $default 默认百分比
* @return int
*/
function getPercentByDays($days, $thresholdMap, $default = 0) {
// 按照阈值从大到小排序
krsort($thresholdMap);
foreach ($thresholdMap as $threshold => $percent) {
if ($days >= $threshold) {
return $percent;
}
}
return $default;
}
// 测试示例
echo getPercentByDays(5, $thresholdMap); // 输出 5
echo getPercentByDays(10, $thresholdMap); // 输出 10
echo getPercentByDays(2, $thresholdMap); // 输出 0
<?php
进阶场景:二分查找优化性能
如果阈值数组的长度很大,遍历匹配的时间复杂度是O(n),可以使用二分查找将时间复杂度降到O(log n),提升匹配效率。
二分查找实现逻辑
首先把阈值提取出来排序,然后通过二分查找找到最后一个小于等于目标天数的阈值索引,再返回对应的百分比:
<?php
/**
* 二分查找匹配天数对应的百分比
* @param int $days 目标天数
* @param array $thresholdMap 阈值映射数组,键为天数,值为百分比
* @param int $default 默认百分比
* @return int
*/
function getPercentByDaysBinary($days, $thresholdMap, $default = 0) {
$thresholds = array_keys($thresholdMap);
sort($thresholds);
$left = 0;
$right = count($thresholds) - 1;
$resultIndex = -1;
// 二分查找最后一个小于等于days的阈值
while ($left <= $right) {
$mid = intval(($left + $right) / 2);
if ($thresholds[$mid] <= $days) {
$resultIndex = $mid;
$left = $mid + 1;
} else {
$right = $mid - 1;
}
}
if ($resultIndex == -1) {
return $default;
}
return $thresholdMap[$thresholds[$resultIndex]];
}
// 测试示例
echo getPercentByDaysBinary(5, $thresholdMap); // 输出 5
echo getPercentByDaysBinary(20, $thresholdMap); // 输出 20
echo getPercentByDaysBinary(1, $thresholdMap); // 输出 0
<?php
两种方案的选择建议
如果阈值数组的长度较小,比如不超过20个,遍历匹配的方案代码更简洁,维护成本更低;如果阈值数组长度很大,或者需要频繁调用匹配函数,建议使用二分查找方案,性能优势会更明显。
另外需要注意,阈值数组的键必须是纯数字类型的天数,避免出现字符串键导致排序或比较逻辑出错。如果业务中存在不连续的区间,比如3-7天给5%,8-15天给10%,只需要调整阈值数组的定义即可,匹配逻辑不需要修改。