如何检查两个切片是否由同一阵列备份?
例如:
a := []int{1, 2, 3}
b := a[0:1]
c := a[2:3]
alias(b, c) == true
alias
应该是什么样?
答案 0 :(得分:3)
通常,您无法确定两个切片之间是否共享了后备数组,因为使用full slice expression可以控制所得切片的容量,因此即使检查容量。
例如,如果您有一个包含10个元素的支持数组,则可能会创建一个仅包含前2个元素的切片,其容量可能是2。并且可能会创建另一个仅包含其后2个元素的切片。 ,其容量再次为2。
请参见以下示例:
a := [10]int{}
x := a[0:2:2]
y := a[8:10:10]
fmt.Println("len(x) = ", len(x), ", cap(x) = ", cap(x))
fmt.Println("len(y) = ", len(y), ", cap(y) = ", cap(y))
上面的代码将打印x
和y
的长度和容量均为2。它们显然具有相同的后备数组,但是您没有任何办法告诉您。
编辑:我误解了这个问题,以下内容描述了如何确定2个切片的(元素)是否重叠。
对此没有语言支持,但是由于切片具有某些后备数组的连续部分,因此我们可以检查其元素的地址范围是否重叠。
不幸的是,在我们无法对它们应用<
和>
运算符的情况下,指针没有排序(Go中有指针,但是没有指针算术)。并检查第一个切片中所有元素的地址是否与第二个切片中的任何地址匹配,这是不可行的。
但是我们可以使用反射包,更具体地说是Value.Pointer()
方法(或者也可以使用包{{1}来实现),将指针值(地址)作为uintptr
类型的指针。 },但unsafe
是“安全”的,并且reflect
值是整数,它们是有序的,因此我们可以对其进行比较。
因此,我们可以做的是获取切片的第一个和最后一个元素的地址,并通过比较它们来确定它们是否重叠。
这是一个简单的实现:
uintptr
测试:
func overlap(a, b []int) bool {
if len(a) == 0 || len(b) == 0 {
return false
}
amin := reflect.ValueOf(&a[0]).Pointer()
amax := reflect.ValueOf(&a[len(a)-1]).Pointer()
bmin := reflect.ValueOf(&b[0]).Pointer()
bmax := reflect.ValueOf(&b[len(b)-1]).Pointer()
return !(amax < bmin || amin > bmax)
}
在Go Playground上尝试。
答案 1 :(得分:0)