递归算法实践--到仓合单助力京东物流提效增收
一、背景
京东物流到仓业务「对商家」为了减少商家按照京东采购单分货备货过程,对齐行业直接按照流向交接,提升商家满意度;「对京东」揽收操作APP提效;到仓合单功能应运而生;
二、问题
一次批量采购单(一次50或者100个采购单)需要根据不同的规则合并成多个订单;
每一个采购单可以是不同的来源类型(自营和非自营)、不同的收货类型,每一个采购单会有多个SKU,同一个SKU只有一个等级,一批采购单会有多个SKU,同一个SKU会有多个等级;
合单规则:
三、打法
A、思路
B、算法
递归算法是一种通过重复将问题分解为同类的子问题来解决问题的方法; 特点是函数或子程序在运行过程中直接或间接调用自身;常见的递归算法包括Fibonacci函数、Hanoi问题和阶乘计算等;
C、解决方案
1. 递归代码块
/**
* 指定不同等级不能合单
*
* @param poNoSet 采购单号Set
* @param poMainInfoMap 采购单详情
* @param calculatedSet 计算过的采购单据列表的集合
* @return
*/
private List<Set<String>> doMergeClassDifferent(Set<String> poNoSet, Map<String, PoOrderFacadeResponse.PoMainInfo> poMainInfoMap, Set<String> calculatedSet) {
// 如果该set已经计算过则不重复计算
List<Set<String>> resultList = new ArrayList<>();
String calculatedPoNoKey = buildCalculatedPoNoKey(poNoSet);
if (calculatedSet.contains(calculatedPoNoKey)) {
return resultList;
} else {
calculatedSet.add(calculatedPoNoKey);
resultValue.incrementAndGet();
}
// 以sku为key的集合
Set<String> skuSet = new HashSet<>();
// 以sku 为key, 值为poNos
Map<String, Set<String>> skuMap = new HashMap<>();
// 存放同一个sku下有多少个不同等级的集合
Map<String, Set<String>> skuToskuLevelMap = new HashMap<>();
// 以sku+level 为key的集合
Set<String> skuLevelSet = new HashSet<>();
// 以sku+level 为key, 值为poNos
Map<String, Set<String>> skuLevelMap = new HashMap<>();
for (String poNo : poNoSet) {
PoOrderFacadeResponse.PoMainInfo poMainInfo = poMainInfoMap.get(poNo);
// 采购单条目
List<PoOrderFacadeResponse.PoItemInfo> poItemInfos = poMainInfo.getPoItemInfos();
for (PoOrderFacadeResponse.PoItemInfo poItemInfo : poItemInfos) {
String skuKey = poItemInfo.getGoodsNo();
String skuLevelKey = buildSkuLevelKey(poItemInfo);
skuSet.add(skuKey);
setKeyMap(skuKey, skuMap, poNo);
// 存放同一个sku下有多少个不同等级的集合
Set<String> stringSet = skuToskuLevelMap.get(skuKey);
if (CollectionUtils.isEmpty(stringSet)) {
stringSet = new HashSet<>();
skuToskuLevelMap.put(skuKey, stringSet);
}
stringSet.add(skuLevelKey);
skuLevelSet.add(skuLevelKey);
setKeyMap(skuLevelKey, skuLevelMap, poNo);
}
}
if (skuSet.size() == skuLevelSet.size()) {
// 此处sku的数量和sku+level的数量相同,不需要再进行递归运算
// 方法结束的出口
resultList.add(poNoSet);
return resultList;
} else {
// 同一个sku下最多等级个数
int high = MagicCommonConstants.NUM_1;
// 最多等级个数的对应sku
String maxLevelSku = "";
for (String sku : skuToskuLevelMap.keySet()) {
Set<String> strings = skuToskuLevelMap.get(sku);
if (strings.size() > high) {
high = strings.size();
maxLevelSku = sku;
}
}
if (high > MagicCommonConstants.NUM_1) {
// 获取该sku下的poNos
Set<String> strings = skuMap.get(maxLevelSku);
// 差集
Set<String> chaJiSet = poNoSet;
chaJiSet.removeAll(strings);
Set<String> skuLevels = skuToskuLevelMap.get(maxLevelSku);
for (String skuLevel : skuLevels) {
Set<String> poNoTempSet = skuLevelMap.get(skuLevel);
poNoTempSet.addAll(chaJiSet);
// 递归计算
List<Set<String>> clist = doMergeClassDifferent(poNoTempSet, poMainInfoMap, calculatedSet);
if (CollectionUtils.isNotEmpty(clist)) {
resultList.addAll(clist);
}
}
}
}
return resultList;
}
2. 去重代码块
/**
* 去重 合单之后的采购单号
*
* @param sets
* @param dooModel
*/
private List<Set<String>> uniqueRepeatPoNo(List<Set<String>> sets, DooModel dooModel) {
sets.sort(new Comparator<Set<String>>() {
@Override
public int compare(Set<String> o1, Set<String> o2) {
return o2.size() - o1.size();
}
});
List<Set<String>> resultList = new ArrayList<>();
Set<String> allMergedSet = new HashSet<>();
Set<String> allSet = new HashSet<>();
for (Set<String> set : sets) {
Set<String> tempSet = new HashSet<>();
for (String poNo : set) {
if (!allSet.contains(poNo)) {
tempSet.add(poNo);
allMergedSet.add(poNo);
}
}
if (!tempSet.isEmpty()) {
if (tempSet.size() > 1) {
allSet.addAll(tempSet);
resultList.add(tempSet);
}
// 此处的单条后面不一定不能合单
}
}
// 差集
allMergedSet.removeAll(allSet);
if (allMergedSet.size() > 0) {
for (String poNo: allMergedSet) {
putPoNoToSet(dooModel, poNo);
}
}
return resultList;
}

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
代码之美-代码整洁之道
一、开篇引言 2024年,跨进21世纪已经两个轮回,这些计算机技术基础问题似乎并没有因为软件工程和计算机相关专业的发展,而有所改善。需求在各个域中表现千差万别,问题在各处代码中也似乎毫无规律,本文说代码之美是希望大家认识代码的美,化繁为简,创造出美好的产品。 代码之美有很多方面,可以谈高级编程语言以及各语言的框架/类库,也可以聊算法和数据结构,还可以谈操作系统内核或是层出不穷的中间件,不过这里我们看最不起眼的代码整洁之道。 从上面两个建筑的对比可以看出:系统整洁度与系统规模非强相关,一切从心开始。 二、整洁之道 说起代码整洁之道,不得不提到人称Bob大叔的Robert C. Martin,以及他写的《Clean Code》一书。 《Clean Code》告诉我们,糟糕的代码也能运行,但如果代码不整洁会使整个团队深陷泥潭,让系统危如累卵,让每一次修改都如履薄冰,每年耗费难以计数的时间、资源和士气。然而这一切并非不可避免。 2.1 什么是整洁代码? 可能有人觉得谈代码太基础,有点low,不够高大上,应该谈谈设计、模型、算法,亦或是业务域;或者也有人觉得随着AI技术发展,代码可以自动生成了;...
-
下一篇
Sylius v2.1.6 发布,PHP 电子商务平台
Sylius 是一个开源的 PHP 电子商务网站框架,基于 Symfony 和 Doctrine 构建,为用户量身定制解决方案。可管理任意复杂的产品和分类,每个产品可以设置不同的税率,支持多种配送方法,集成 Omnipay 在线支付。 Sylius 2.1.6 现已发布,该版本更新内容如下: #18362[CS][DX] Refactor #18111[Composer] 将 PHPUnit 升级到 ^11.5 + run Rector rule #18370[CS][DX] Refactor #18364[BUGFIX] 修正产品变体视图中的定价货币解析 #18386[CI] 在所有工作流矩阵中将Symfony从7.2升级至7.3 #18387[Refactor] 从测试中删除未使用的 Connection 模拟 #18361[DEPRECATIONS] 将CartActions接口和OrderItemController标记为已弃用 #18378[AdminBundle] 当用户商店帐户被锁定时隐藏 Impersonate 按钮 #18375[CI] 同时测试 API Platfo...
相关文章
文章评论
共有0条评论来说两句吧...