PHP按嵌套数组最小值及差值规则排序库存更新数组
PHP库存数组多规则排序实现方案
原数组
$stock_updates = [ 'sku1234' => [ 'current_stock' => [ 'id1' => 6, 'id2' => 23, 'id3' => 90, 'id4' => 61, ], 'actual_stock' => 400, ], 'sku5678' => [ 'current_stock' => [ 'id1' => 3, 'id2' => 3, 'id3' => 4, 'id4' => 11, ], 'actual_stock' => 0, ], 'sku9012' => [ 'current_stock' => [ 'id1' => 1000, 'id2' => 1, 'id3' => 56, 'id4' => 234, ], 'actual_stock' => 100, ], 'sku3456' => [ 'current_stock' => [ 'id1' => 0, 'id2' => 0, 'id3' => 1, 'id4' => 0, ], 'actual_stock' => 200, ], 'sku1123' => [ 'current_stock' => [ 'id1' => 10, 'id2' => 50, 'id3' => 234, 'id4' => 61, ], 'actual_stock' => 5, ], ];
排序规则
- 先计算每个SKU的
current_stock最小值 - 第一优先级:最小值>0且
actual_stock=0的项,排在最前面 - 第二优先级:
current_stock最小值=0且actual_stock>0的项,排在第一优先级之后 - 其余项按
actual_stock与current_stock最小值的差值从大到小排序
预期排序结果
$stock_updates_ordered = [ // 第一优先级:显示有库存但实际无库存 'sku5678' => [ 'current_stock' => [ 'id1' => 3, 'id2' => 3, 'id3' => 4, 'id4' => 11, ], 'actual_stock' => 0, 'priority' => PHP_INT_MAX, ], // 其余组:实际库存低于显示的最低库存 'sku1123' => [ 'current_stock' => [ 'id1' => 10, 'id2' => 50, 'id3' => 234, 'id4' => 61, ], 'actual_stock' => 5, 'priority' => PHP_INT_MAX - 5, ], // 第二优先级:显示无库存但实际有库存 'sku3456' => [ 'current_stock' => [ 'id1' => 0, 'id2' => 0, 'id3' => 1, 'id4' => 0, ], 'actual_stock' => 200, 'priority' => PHP_INT_MAX - 10, ], // 其余组:库存差值从大到小 'sku1234' => [ 'current_stock' => [ 'id1' => 6, 'id2' => 23, 'id3' => 90, 'id4' => 61, ], 'actual_stock' => 400, 'priority' => 394, ], 'sku9012' => [ 'current_stock' => [ 'id1' => 1000, 'id2' => 1, 'id3' => 56, 'id4' => 234, ], 'actual_stock' => 100, 'priority' => 99, ], ];
实现思路
- 预处理计算最小值:遍历一次数组,为每个SKU计算
current_stock的最小值,避免排序时重复计算,提升效率(尤其500条数据的规模) - 关联数组排序:用
uasort函数,它能保留SKU的键名,适合处理关联数组排序 - 优先级分组判断:在排序回调里给每个元素划分优先级组,组间按规则排序,组内按差值排序
- 组内排序逻辑:其余项按
actual_stock - 最小值的差值从大到小排列
代码实现
匹配规则描述的基础版本
// 预处理:为每个SKU添加current_min字段(存储current_stock的最小值) array_walk($stock_updates, function(&$item) { $item['current_min'] = min($item['current_stock']); }); // 自定义排序逻辑 uasort($stock_updates, function($a, $b) { // 为元素划分优先级组 $groupA = 3; // 默认第三组 if ($a['current_min'] > 0 && $a['actual_stock'] === 0) { $groupA = 1; // 第一优先级组 } elseif ($a['current_min'] === 0 && $a['actual_stock'] > 0) { $groupA = 2; // 第二优先级组 } $groupB = 3; if ($b['current_min'] > 0 && $b['actual_stock'] === 0) { $groupB = 1; } elseif ($b['current_min'] === 0 && $b['actual_stock'] > 0) { $groupB = 2; } // 组间排序:组1 > 组2 > 组3 if ($groupA !== $groupB) { return $groupA - $groupB; // 组号越小优先级越高,排前面 } // 第三组内部按差值从大到小排序 if ($groupA === 3) { $diffA = $a['actual_stock'] - $a['current_min']; $diffB = $b['actual_stock'] - $b['current_min']; return $diffB - $diffA; // 差值大的排前面 } // 同组内无额外排序需求时返回0,保持原相对顺序 return 0; }); // 可选:删除预处理添加的current_min字段 array_walk($stock_updates, function(&$item) { unset($item['current_min']); }); // 输出结果 print_r($stock_updates);
匹配示例顺序的调整版本
如果要完全和你给出的示例顺序一致(将实际库存低于显示最低库存的项放在第二优先级前面),只需调整优先级组的划分逻辑:
uasort($stock_updates, function($a, $b) { // 重新定义优先级组 $groupA = 4; // 默认第四组 if ($a['current_min'] > 0 && $a['actual_stock'] === 0) { $groupA = 1; // 第一优先级 } elseif ($a['actual_stock'] < $a['current_min']) { $groupA = 2; // 实际库存不足的情况 } elseif ($a['current_min'] === 0 && $a['actual_stock'] > 0) { $groupA = 3; // 第二优先级 } $groupB = 4; if ($b['current_min'] > 0 && $b['actual_stock'] === 0) { $groupB = 1; } elseif ($b['actual_stock'] < $b['current_min']) { $groupB = 2; } elseif ($b['current_min'] === 0 && $b['actual_stock'] > 0) { $groupB = 3; } if ($groupA !== $groupB) { return $groupA - $groupB; } // 第四组内部按差值从大到小排序 if ($groupA === 4) { $diffA = $a['actual_stock'] - $a['current_min']; $diffB = $b['actual_stock'] - $b['current_min']; return $diffB - $diffA; } return 0; });
内容的提问来源于stack exchange,提问作者Craig Pearson
相关产品推荐
相关产品推荐

