原来的需求是这样的,用户生成了400元订单,需要400元的发票去抵消,发票数和订单数不受限制,
将问题拟物化,订单可以想象成杯子,发票可以想象成水,现在要把水分配到每个杯子中去
我们先记录每个杯子的起始值和结束值,还有当前值,起始值(start)=当前杯子的起始值加上上一个杯子的结束值,结束值(end)即起始值加上杯子的容量,当前值(index)即当前杯子中的水,如果大于杯子的容量则倒下一个杯子,依次循环,所以其实整个倒水可以看做一个大杯子,按阶段倒水,每次记录倒水的index(即当前(或者当次)杯子中的水即可)
现在假设a杯50L, b杯20L
假如第一次倒, a[0, 50]杯子倒满,剩余20;index = 50 , start = 0 , end = 50;
第二次倒b杯[50, 70], 首先拿上一下剩余的20L, 刚好倒满,index = 20; start = 50 ,end = 70
依次类推
话不多说,上代码
export function getItemDistribution(a, b, waterKey, cupKey, policyId) {
class ItemDistribution {
cupList = [];
result = [];
constructor(list, maps) {
this.waterKey = waterKey;
this.cupKey = cupKey;
this.policyId = policyId;
this.sort(list, maps);
this.init(list);
}
sort(list, maps) {
let {waterKey, cupKey} = this;
if (waterKey) {
list = list.sort((a, b) => a[waterKey] - b[waterKey]);
} else {
list = list.sort((a, b) => a - b);
}
if (cupKey) {
maps = maps.sort((a, b) => a[cupKey] - b[cupKey]);
} else {
maps = maps.sort((a, b) => a - b);
}
this.list = list;
this.maps = maps;
return {list, maps}
}
init(list) {
if (list == null || list.length <= 0) {
return;
}
let start = 0, end = 0, index = 0;
let {waterKey} = this;
list.forEach((item, id) => {
if (!waterKey) {
this.result[id] = [];
}
let water = waterKey ? item[waterKey] : item;
end = start + Number(water);
this.entry({start, index, end});
start = end;
});
this.dispatchMaps();
}
entry({start, index, end}) {
index = start;
this.cupList.push({start, end, index})
}
dispatchMaps() {
function isEmpty(o) {
switch (JSON.stringify(o)) {
case 'null':
case undefined:
return true;
case '[]':
return true;
}
return false;
}
let {maps = [], cupList, cupKey} = this;
if (isEmpty(cupList) || isEmpty(maps)) return false;
maps.forEach((item, id) => {
let cup = cupKey ? item[cupKey] : item;
this.dispatchCup({item: cup, id});
});
}
getCup() {
function isEqual(a, b) {
return String(a.toFixed(2)) !== String(b.toFixed(2));
}
let {cupList} = this;
for (let i = 0; i < cupList.length; i++) {
let item = cupList[i];
if (isEqual(item.end, item.index)) {
return {cup: item, cupIndex: i};
}
}
return {};
}
dispatchCup({item, id}) {
let {cup, cupIndex} = this.getCup();
if (!cup) return false;
let {index, end} = cup;
let remain = end - index;
let {waterKey, list, policyId, maps} = this;
if (remain > item) {
cup.index = cup.index + item;
waterKey ? this.result.push({
...list[cupIndex],
[waterKey]: item,
[policyId]: maps[id][policyId]
}) : this.result[id].push(item);
return false;
} else {
cup.index = cup.end;
waterKey ? this.result.push({
...list[cupIndex],
[waterKey]: remain,
[policyId]: maps[id][policyId]
}) : this.result[id].push(remain);
item -= remain;
this.dispatchCup({item, id})
}
}
}
return new ItemDistribution(a, b);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。