IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 整数区间计算,我这么设计 -> 正文阅读

[开发测试]整数区间计算,我这么设计

作者:token keyword

整数区间的交集和差集样例:

[1,5] + [6,10] = [1,10]

[1,100] - [10,20] = [1,9] + [21,100]

如果让你设计一个程序,能够计算整数区间的合集、交集、差集,你会怎么设计?

我会默默想想难度,然后去github上找找有没有可复用的开源代码。

go-intervals简介

go-intervals是一个用于在一维区间(例如时间范围)上执行集合操作的库,正好能满足我的整数区间计算需求。github地址为:https://github.com/google/go-intervals/

选用原因

之所以选择go-intervals有三个方面的考虑:

  1. 背靠谷歌金字招牌,足够让我相信代码质量

  2. 完整的测试用例

  3. 代码开源且易懂

代码剖析

go-intervals库能对多种一维区间集合进行操作,如时间、整数等;也能支持多种开闭区间,如左开右闭、左闭右开、左闭右闭等。代码是如何进行设计的呢?难道作者在代码内部实现了所有细节?

依赖倒转原则(DIP):高层模块不要依赖低层模块。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。具体内容在Go设计模式(3)-设计原则有讲述。

思路:多个区间构成一个集合,区间是集合的基本单位。集合的交差并操作本质上是区间的交差并操作。

结合上面两点,作者的实现方式是将区间接口化。go-intervals只负责将在框架层面将两个集合的区间,两两进行交并差操作,交并差的实现逻辑由调用者自己实现。

type Interval interface {
  // Intersect returns the intersection of an interval with another
  // interval. The function may panic if the other interval is incompatible.
  //交集
  Intersect(Interval) Interval

  // Before returns true if the interval is completely before another interval.
  //一个区间是否在另一个区间前面
  Before(Interval) bool

  // IsZero returns true for the zero value of an interval.
  //是否为空区间
  IsZero() bool

  // Bisect returns two intervals, one on the lower side of x and one on the
  // upper side of x, corresponding to the subtraction of x from the original
  // interval. The returned intervals are always within the range of the
  // original interval.
  //差集
  Bisect(x Interval) (Interval, Interval)

  // Adjoin returns the union of two intervals, if the intervals are exactly
  // adjacent, or the zero interval if they are not.
  //并集
  Adjoin(Interval) Interval

  // Encompass returns an interval that covers the exact extents of two
  // intervals.
  //区间是否为包含关系
  Encompass(Interval) Interval
}

实现

调用者想实现哪种区间、哪种开闭方式,只需要实现自己的Interval即可。我需要实现整数、左闭右闭区间的并集、差集操作。

左闭右开区间

在代码的测试用例中,作者给出了整数区间,左闭右开的实现:

type span struct {
	min, max int
}

// case returns a *span from an Interval interface, or it panics.
func cast(i Interval) *span {
	x, ok := i.(*span)
	if !ok {
		panic(fmt.Errorf("interval must be an span: %v", i))
	}
	return x
}

// zero returns the zero value for span.
func zero() *span {
	return &span{}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func (s *span) String() string {
	return fmt.Sprintf("[%d, %d)", s.min, s.max)
}

func (s *span) Equal(t *span) bool {
	return s.min == t.min && s.max == t.max
}

// Intersect returns the intersection of an interval with another
// interval. The function may panic if the other interval is incompatible.
func (s *span) Intersect(tInt Interval) Interval {
	t := cast(tInt)
	result := &span{
		max(s.min, t.min),
		min(s.max, t.max),
	}
	if result.min < result.max {
		return result
	}
	return zero()
}

// Before returns true if the interval is completely before another interval.
func (s *span) Before(tInt Interval) bool {
	t := cast(tInt)
	return s.max <= t.min
}

// IsZero returns true for the zero value of an interval.
func (s *span) IsZero() bool {
	return s.min == 0 && s.max == 0
}

// Bisect returns two intervals, one on either lower side of x and one on the
// upper side of x, corresponding to the subtraction of x from the original
// interval. The returned intervals are always within the range of the
// original interval.
func (s *span) Bisect(tInt Interval) (Interval, Interval) {
	intersection := cast(s.Intersect(tInt))
	if intersection.IsZero() {
		if s.Before(tInt) {
			return s, zero()
		}
		return zero(), s
	}
	maybeZero := func(min, max int) *span {
		if min == max {
			return zero()
		}
		return &span{min, max}
	}
	return maybeZero(s.min, intersection.min), maybeZero(intersection.max, s.max)

}

// Adjoin returns the union of two intervals, if the intervals are exactly
// adjacent, or the zero interval if they are not.
func (s *span) Adjoin(tInt Interval) Interval {
	t := cast(tInt)
	if s.max == t.min {
		return &span{s.min, t.max}
	}
	if t.max == s.min {
		return &span{t.min, s.max}
	}
	return zero()
}

// Encompass returns an interval that covers the exact extents of two
// intervals.
func (s *span) Encompass(tInt Interval) Interval {
	t := cast(tInt)
	return &span{min(s.min, t.min), max(s.max, t.max)}
}

左闭右闭区间

既然作者提供的不满足需求,就需要自己进行修改。参考左闭右开代码修改为左闭右闭代码,目前唯一的缺点是如果构建集合的区间有重叠会panic,重叠问题可以在业务层进行检查,倒也没什么问题。

type span struct {
   min, max int64
}

// case returns a *span from an Interval interface, or it panics.
func cast(i intervalset.Interval) *span {
   x, ok := i.(*span)
   if !ok {
      panic(fmt.Errorf("interval must be an span: %v", i))
   }
   return x
}

// zero returns the zero value for span.
func zero() *span {
   return &span{}
}

func min(a, b int64) int64 {
   if a < b {
      return a
   }
   return b
}

func max(a, b int64) int64 {
   if a > b {
      return a
   }
   return b
}

func (s *span) String() string {
   return fmt.Sprintf("[%d, %d]", s.min, s.max) //done
}

func (s *span) Equal(t *span) bool {
   return s.min == t.min && s.max == t.max
}

//已修改
// Before returns true if the interval is completely before another interval.
func (s *span) Before(tInt intervalset.Interval) bool {
   t := cast(tInt)
   //if s.min == s.max && s.max == t.min && t.min == t.max { //done
   // return false
   //}
   //if (s.min == s.max) && (s.min == t.min || s.min == t.max || s.max == t.min || s.max == t.max) {
   // return false
   //}
   //if (t.min == t.max) && (t.min == s.max || t.min == s.min || t.max == s.max || t.max == s.min) {
   // return false
   //}

   return s.max < t.min
}

// IsZero returns true for the zero value of an interval.
func (s *span) IsZero() bool {
   return s.min == 0 && s.max == 0
}

//交集 已修改
// Intersect returns the intersection of an interval with another
// interval. The function may panic if the other interval is incompatible.
func (s *span) Intersect(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   result := &span{
      max(s.min, t.min),
      min(s.max, t.max),
   }
   if result.min <= result.max { //done
      return result
   }
   return zero()
}

//相邻拼接  已修改
// Adjoin returns the union of two intervals, if the intervals are exactly
// adjacent, or the zero interval if they are not.
func (s *span) Adjoin(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   if s.max == t.min || s.max == t.min-1 { //done
      return &span{s.min, t.max}
   }
   if t.max == s.min || t.max == s.min-1 { //done
      return &span{t.min, s.max}
   }
   return zero()
}

//差集 已修改
// Bisect returns two intervals, one on either lower side of x and one on the
// upper side of x, corresponding to the subtraction of x from the original
// interval. The returned intervals are always within the range of the
// original interval.
func (s *span) Bisect(tInt intervalset.Interval) (intervalset.Interval, intervalset.Interval) {
   intersection := cast(s.Intersect(tInt))
   if intersection.IsZero() {
      if s.Before(tInt) {
         return s, zero()
      }
      return zero(), s
   }
   maybeZero := func(min, max int64) *span {
      if min > max { //done
         return zero()
      }
      return &span{min, max}
   }
   return maybeZero(s.min, intersection.min-1), maybeZero(intersection.max+1, s.max) //done

}

// Encompass returns an interval that covers the exact extents of two
// intervals.
func (s *span) Encompass(tInt intervalset.Interval) intervalset.Interval {
   t := cast(tInt)
   return &span{min(s.min, t.min), max(s.max, t.max)}
}

测试

检验自己代码是否有问题有什么方法?至少有两点,一是代码review,二是单元测试。对于这种引入的第三方库、且自己实现部分逻辑,一定要做好单元测试,这是前人栽树后人乘凉的好事。

测试case整理如下:

图片

[20,40]为指定区间,用其它区间和指定区间进行交、差操作。竖线表示左右区间值一样。

写了一晚上测试用例,初步测试没有问题。

/**
@author: Jason Pang
@desc:
@date: 2021/7/1
**/
package service

import (
   "github.com/google/go-intervals/intervalset"
   "reflect"
   "testing"
)

func TestAddTest(t *testing.T) {
   type args struct {
      s1 *intervalset.Set
      s2 *intervalset.Set
   }
   tests := []struct {
      name    string
      args    args
      wantRes *intervalset.Set
   }{
      {
         name: "empty + empty = empty",
         args: args{
            s1: intervalset.NewSet([]intervalset.Interval{}),
            s2: intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "empty + [30,111] = [30, 111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{}),
            intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
      },
      {
         name: "[20, 40] + empty = [20, 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] + [60,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{60, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}, &span{60, 111}}),
      },
      {
         name: "[20, 40] + [39,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 111}}),
      },
      {
         name: "[20, 40] + [40,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 111}}),
      },
      {
         name: "[20, 40] + [41,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 111}}),
      },
      {
         name: "[20, 40] + [30,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 111}}),
      },
      {
         name: " [20,40] + [25, 28]  = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25, 28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: " [20,40] + [10, 30]  = [10,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 30}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 40}}),
      },
      {
         name: "[10, 19] + [20,40]  = [10,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10, 19}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 40}}),
      },
      {
         name: "[20,40] + [10, 20]  = [10,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 40}}),
      },
      {
         name: "[20,40] + [10, 21]  = [10,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 40}}),
      },
      {
         name: "[20,40] + [10, 15]  = [10,15] [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 15}, &span{20, 40}}),
      },
      {
         name: "[20,40] + [10, 100]  = [10,100]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 100}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 100}}),
      },
      {
         name: "[20,40] + [10, 10]  = [10,10] [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 10}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 10}, &span{20, 40}}),
      },
      {
         name: "[20,40] + [19, 19]  = [19 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{19, 19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{19, 40}}),
      },
      {
         name: "[20,40] + [20, 20]  = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20,40] + [21, 21]  = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{21, 21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20,40] + [25, 25]  = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25, 25}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20,40] + [39, 39]  = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39, 39}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20,40] + [40, 40]  = [20 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40, 40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20,40] + [41, 41]  = [20 41]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41, 41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 41}}),
      },
      {
         name: "[20,40] + [50, 50]  = [20 40] [50, 50] ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{50, 50}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}, &span{50, 50}}),
      },
      /
      {
         name: "[20, 40] + [41,50]+ [50,60]+ [61,111] = [20,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}, &span{41, 50}}),
            intervalset.NewSet([]intervalset.Interval{&span{50, 60}, &span{61, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 111}}),
      },

      {
         name: "[10, 19] +  [20,20] = [10,20]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10, 19}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 20}}),
      },
      {
         name: " [20,20] + [10, 19]  = [10,20]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 20}}),
      },
      {
         name: "[10, 19] + [21,30] + [20,20]  = [10,30]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10, 19}, &span{21, 30}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 30}}),
      },
      {
         name: "[10, 15] +  [20,20]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{10, 15}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 15}, &span{20, 20}}),
      },
      {
         name: " [20,20] + [10, 15]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{10, 15}, &span{20, 20}}),
      },
   }
   for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) {
         if gotRes := AddTest(tt.args.s1, tt.args.s2); !reflect.DeepEqual(gotRes.AllIntervals(), tt.wantRes.AllIntervals()) {
            t.Errorf("Add() = %v, want %v", gotRes, tt.wantRes)
         }
      })
   }
}

func TestSubTest(t *testing.T) {
   type args struct {
      s1 *intervalset.Set
      s2 *intervalset.Set
   }
   tests := []struct {
      name    string
      args    args
      wantRes *intervalset.Set
   }{
      {
         name: "empty - empty = empty",
         args: args{
            s1: intervalset.NewSet([]intervalset.Interval{}),
            s2: intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "empty - [30,111] = empty",
         args: args{
            intervalset.NewSet([]intervalset.Interval{}),
            intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: "[30,111] - empty = [30,111]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
            intervalset.NewSet([]intervalset.Interval{}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
      },
      {
         name: "[20, 40] - [30,111] = [20,29]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{30, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 29}}),
      },
      {
         name: "[20, 40] - [41,111] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [40,111] = [20,39]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 39}}),
      },
      {
         name: "[20, 40] - [39,111] = [20,38]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39, 111}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 38}}),
      },
      {
         name: "[20, 40] - [25,28] = [20,24] [29,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25, 28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 24}, &span{29, 40}}),
      },
      {
         name: "[20, 40] - [15,28] = [29,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15, 28}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{29, 40}}),
      },
      {
         name: "[20, 40] - [15,20] = [21,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{21, 40}}),
      },
      {
         name: "[20, 40] - [15,21] = [22,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15, 21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{22, 40}}),
      },
      {
         name: "[20, 40] - [15,19] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{15, 19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [10,15] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{10, 15}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [5,5] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{5, 5}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [20,20] = [21,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 20}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{21, 40}}),
      },
      {
         name: "[20, 40] - [25,25] = [20,24] [26,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{25, 25}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 24}, &span{26, 40}}),
      },
      {
         name: "[20, 40] - [40,40] = [20,39]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{40, 40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 39}}),
      },
      {
         name: "[20, 40] - [45,45] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{45, 45}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [19,19] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{19, 19}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [21,21] = [20,20] [22,40] ",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{21, 21}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 20}, &span{22, 40}}),
      },
      {
         name: "[20, 40] - [39,39] = [20,38] [40, 40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{39, 39}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 38}, &span{40, 40}}),
      },
      {
         name: "[20, 40] - [41,41] = [20,40]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{41, 41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
      },
      {
         name: "[20, 40] - [11,41] = []",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
            intervalset.NewSet([]intervalset.Interval{&span{11, 41}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{}),
      },
      {
         name: " [11,41] - [20, 40]  = [11,19] [41 41]",
         args: args{
            intervalset.NewSet([]intervalset.Interval{&span{11, 41}}),
            intervalset.NewSet([]intervalset.Interval{&span{20, 40}}),
         },
         wantRes: intervalset.NewSet([]intervalset.Interval{&span{11, 19}, &span{41, 41}}),
      },
   }
   for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) {
         if got := SubTest(tt.args.s1, tt.args.s2); !reflect.DeepEqual(got.AllIntervals(), tt.wantRes.AllIntervals()) {
            t.Errorf("Sub() = %v, want %v", got, tt.wantRes)
         }
      })
   }
}

总结

很多时候真的不需要重复造轮子,而且也难说自己造的比别人的好,合理合法利用资源、按时完成任务有时候更加重要。写代码是谨小慎微的事情,单元测试必不可少。不但能帮助自己理清思路、发现问题,也能防止后来人改出错误。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-08-06 10:07:54  更:2021-08-06 10:09:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 20:44:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码