拆单情况下,多个订单在不同时间段的总退票费计算——区间交叉计算的通用算法...

这个是在做机票相关业务时遇到的问题。

机票订单会根据情况被拆为多单,每单在不同时间范围内对应不同的退票费。

因为订单退改是一起退改,所以提供给用户的是两个订单总的退票费。

这就需要对多个订单在不同时间段的退票费进行交叉求和。

本处为方便,以订单被拆为两单为例。

如下,订单被拆为两单,两单在不同时间段退票费分别如下

 

求所有时间段的退票费。

即,求出

0——3——5——8——9——10

各个区间的退票费。

 

算法如下:

定义一个退票费的类如下,用来表示一个区间的起始以及对应包含的退票费。

    /// <summary>
    /// 时间段对应退票费列表
    /// </summary>
    class RefundFeeRange
    {
        public RefundFeeRange(int st, int en, List<int> fl)
        {
            Start = st; End = en; Fees = fl;
        }
        //起始时间点
        public int Start { get; set; }
        //结束时间点
        public int End { get; set; }
        //时间段内退票费
        public List<int> Fees { get; set; } }

 

 两个区间交叉的情况是很多的,但区间不交叉的情况只有两种,a在b前,或者b在a前。

判断区间交叉,只要把不交叉的情况进行非处理即可。

方法如下:

        //判断两个时间段是否交叉
        static bool IsTimeConflict(RefundFeeRange a, RefundFeeRange b)
        {
            return !( a.Start >= b.End || a.End <= b.Start );
        }

 

求区间交叉后的值的方法如下:

  根据所有区间起始点,取出不重复节点

  根据这些节点,得出新的不交叉的区间

  用这些新的区间分别和旧的各个区间进行交叉判断,如果交叉就把对应值放入列表

  返回新的集合即可

具体代码如下:

       /// <summary>
        /// 由多个可能冲突的时间段对应退票费,算出不冲突的时间段的退票费集合
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        static List<RefundFeeRange> RefundFeeCaculate(List<RefundFeeRange> param)
        {
            //时间段对应退票费集合
            var temps = new List<RefundFeeRange>();
            //获得所有不重复的时间点集合
            var timePointList = new List<int>();
            param.ForEach(x =>
            {
                timePointList.Add(x.Start);
                timePointList.Add(x.End);
            });
            timePointList = timePointList.OrderBy(x => x).Distinct().ToList();
            //获得所有不冲突的时间段集合
            for (int i = 0; i < timePointList.Count - 1; i++) { temps.Add(new RefundFeeRange(timePointList[i], timePointList[i + 1], new List<int>())); } //获得每个时间段内对应的不同航班的退票费 temps.ForEach(x => { param.ForEach(y => { if (IsTimeConflict(x, y)) { x.Fees.AddRange(y.Fees); } }); }); return temps; }

 

以前面的例子中的两个订单退票费数据为例计算

        static void Main(string[] args)
        {
            var li = new List<RefundFeeRange>() {
                new RefundFeeRange(0,5,new List<int>(){100}),
                new RefundFeeRange(5,8,new List<int>(){200}),
                new RefundFeeRange(8,10,new List<int>(){300}),
                new RefundFeeRange(0,3,new List<int>(){150}), new RefundFeeRange(3,9,new List<int>(){220}), new RefundFeeRange(9,10,new List<int>(){330}) }; var temps = RefundFeeCaculate(li); temps.ForEach(x => { Console.WriteLine(String.Format("{0}------{1}--------{2} : {3}", x.Start, x.End, x.Fees.Sum(), string.Join(",", x.Fees))); }); Console.ReadLine(); }

输出结果如下

 

对比实际,可以看出结果相符。

 

 

 

转载于:https://www.cnblogs.com/yuwen/p/10318542.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值