资讯专栏INFORMATION COLUMN

JS 多发票多金额分配

source / 1543人阅读

摘要:原来的需求是这样的,用户生成了元订单,需要元的发票去抵消,发票数和订单数不受限制,将问题拟物化,订单可以想象成杯子,发票可以想象成水,现在要把水分配到每个杯子中去我们先记录每个杯子的起始值和结束值,还有当前值,起始值当前杯子的起始值加上上一

原来的需求是这样的,用户生成了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);
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96027.html

相关文章

  • 用css动态实现圆环百分比分配——初探css3动画

    摘要:鑫大佬这篇博文的重点还是在渐变,而我需要动态平缓连续得实现颜色的分配,比如原本整个环是绿色,然后慢慢地被红色占了,而且整个过程要平滑。 最近的小程序项目有个设计图要求做一个圆环,两种颜色分配,分别代表可用金额和冻结金额。要是就直接这么显示,感觉好像挺没水平??于是我决定做个动态! 在mdn把新特性gradients(渐变)、transitions(过渡)、 animations(动画)...

    cheukyin 评论0 收藏0
  • 用css动态实现圆环百分比分配——初探css3动画

    摘要:鑫大佬这篇博文的重点还是在渐变,而我需要动态平缓连续得实现颜色的分配,比如原本整个环是绿色,然后慢慢地被红色占了,而且整个过程要平滑。 最近的小程序项目有个设计图要求做一个圆环,两种颜色分配,分别代表可用金额和冻结金额。要是就直接这么显示,感觉好像挺没水平??于是我决定做个动态! 在mdn把新特性gradients(渐变)、transitions(过渡)、 animations(动画)...

    stormgens 评论0 收藏0
  • 多发短信的平台如何选择?

    摘要:当今社会是一个信息化的时代,多企业苦于找不到一个合适的短信群发平台,选择一个合适的短信服务平台不仅可以高效推送,还可以节约成本。最后看选择的公司价钱是否合适,性价比高不高,如何计费市面上高的七八分,低的三四分分,但太低的可能会有风险。当今社会是一个信息化的时代,多企业苦于找不到一个合适的短信群发平台,选择一个合适的短信服务平台不仅可以高效推送,还可以节约成本。下面我们就来了解下如何选择一个合...

    3119555200 评论0 收藏0
  • java并发编程学习18--最迷你的抢红包

    摘要:业务分析要完成抢红包的功能重点有两个多线程并发修改数据红包现金分配算法类设计用户对象包含用户名称,所抢到的金额,最后的提示文言字段抢红包的用户用户昵称用户抢到的金额用户获得系统提示文言并发访问的共享红包对象这个对象包含了预分配的所有小红包并 【业务分析 要完成抢红包的功能重点有两个: 多线程并发修改数据 红包现金分配算法 【类设计 用户对象:包含用户名称,所抢到的金额,最后的提示文...

    caohaoyu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<