需求背景:用户最优优惠券选择策略
核心思路是取到用户的可用优惠券列表,对列表排序,排序后第一个数组元素为最优优惠券。
Lua 脚本实现的 coupon接口中使用 table.sort 排序;
PHP 使用哪个函数呢?
答案是: usort() 可以实现对数组自定义排序。
usort 的排序规则:
usort($arr, function ($a, $b){
// 这里添加了 order 字段, 默认为0, 将order大的提到前边
return $b['order'] - $a['order'];
});
原文:https://cloud.tencent.com/developer/article/1627906
不稳定: php的usort是不稳定的, 也就是在两个元素相等的情况下, 不能够保证两个元素的位置不变.
总结
再回想一下, 最开始的问题, 当数组长度小于4的时候, 顺序没有改变, 这个因为使用了稳定的插入排序. 当数组长度100的时候, 使用了不稳定的快速排序.
之后使用usort函数, 就把他当做不稳定的就可以了. 这样基本不会有问题的. 但是, 讲话了, 如果我就是需要一个稳定的排序算法怎么办?
官方函数推荐:https://www.php.net/manual/zh/function.uasort.php
uasort — 使用用户自定义的比较函数,保持索引和值的对应关系,原地排序 array。
lua 实现如下:
newPrice: 优惠后价格
discountTypeId:优惠券类型,2=满减
cutAmount:立减金额
expTime:过期时间
-- 按照价格,优惠券类型,优惠券满减金额与失效时间排
table.sort(sortedTable, function(A,B)
if A.newPrice==B.newPrice then
if A.discountTypeId==B.discountTypeId then
if A.discountTypeId == 2 then
return A.cutAmount<B.cutAmount
end
return A.expTime<B.expTime
end
return A.discountTypeId>B.discountTypeId
end
return A.newPrice<B.newPrice
end)
使用PHP实现如下:
protected static function bestCouponStrategy($couponList){
usort($couponList, function($cpA, $cpB){
if($cpA->newPrice==$cpB->newPrice){
if($cpA->disTypeId==$cpB->disTypeId){
if(2==$cpA->disTypeId){
return $cpA->cutAmount < $cpB->cutAmount;
}
return $cpA->expTime < $cpB->expTime;
}
return $cpA->disTypeId > $cpB->disTypeId;
}
return $cpA->newPrice < $cpB->newPrice;
});
}
$cpListA = new stdClass;
$cpListA->newPrice = 100;
$cpListA->discount_type_id = 2;
$cpListA->cut_amount = 50;
$cpListA->expire_time = '20221017235959';
$cpListB = new stdClass;
$cpListB->newPrice = 200;
$cpListB->discount_type_id = 2;
$cpListB->cut_amount = 150;
$cpListB->expire_time = '20221016235959';
$cpListC = new stdClass;
$cpListC->newPrice = 200;
$cpListC->discount_type_id = 2;
$cpListC->cut_amount = 150;
$cpListC->expire_time = '20221015235959';
$couponList[] = $cpListA;
$couponList[] = $cpListB;
$couponList[] = $cpListC;
$res = Coupon::bestCouponStrategy($couponList);
var_dump($res);
php 改进版:
usort($couponList, function($cpA, $cpB) use ($retailPrice){
$cpA->newPrice = (0>=$retailPrice-$cpA->worth*100) ? 0 : $retailPrice-$cpA->worth*100;
$cpB->newPrice = (0>=$retailPrice-$cpB->worth*100) ? 0 : $retailPrice-$cpB->worth*100;
// $cpA->newPrice = $retailPrice-$cpA->worth*100;
// $cpB->newPrice = $retailPrice-$cpB->worth*100;
if($cpA->newPrice==$cpB->newPrice){
if($cpA->type==$cpB->type){
if('FULL_REDUCTION' == $cpA->type){
// return $cpA->worth < $cpB->worth;
if($cpA->worth == $cpB->worth){
return ($cpA->endTime < $cpB->endTime) ? -1 : 1;
// return 0;
}
// return ($cpA->worth > $cpB->worth) ? -1 : 1;
return ($cpA->worth < $cpB->worth) ? -1 : 1;
// return $cpA->worth <=> $cpB->worth; // php7 才支持
}
// return ($cpA->endTime > $cpB->endTime) ? -1 : 1;
return ($cpA->endTime < $cpB->endTime) ? -1 : 1;
}
// return $cpA->type > $cpB->type;
return strcmp($cpA->type, $cpB->type);
}
echo $cpA->newPrice, ": ",$cpB->newPrice, PHP_EOL;
// return ($cpA->newPrice > $cpB->newPrice) ? -1 : 1;
return ($cpA->newPrice < $cpB->newPrice) ? -1 : 1; //倒序
});
网友评论