arrays - 切片的别名
问题描述
如何检查两个切片是否由同一个数组备份?
例如:
a := []int{1, 2, 3}
b := a[0:1]
c := a[2:3]
alias(b, c) == true
应该怎么alias
看?
解决方案
一般来说,您无法判断后备数组是否在 2 个切片之间共享,因为使用完整切片表达式,可能会控制结果切片的容量,然后即使检查容量也不会重叠。
例如,如果您有一个包含 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 个切片的(元素)是否重叠。
对此没有语言支持,但由于切片具有某个后备数组的连续部分,我们可以检查其元素的地址范围是否重叠。
不幸的是,指针不是有序的,因为我们不能对它们应用<
and>
运算符(Go 中有指针,但没有指针算术)。并且检查第一个切片元素的所有地址是否与第二个切片中的任何一个匹配,这是不可行的。
但是我们可以获得一个指针值(一个地址)作为uintptr
使用反射包的一种类型,更具体地说是Value.Pointer()
方法(或者我们也可以使用包来做到这一点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)
}
测试它:
a := []int{0, 1, 2, 3}
b := a[0:2]
c := a[2:4]
d := a[0:3]
fmt.Println(overlap(a, b)) // true
fmt.Println(overlap(b, c)) // false
fmt.Println(overlap(c, d)) // true
在Go Playground上尝试一下。
推荐阅读
- html - 从右上角和右下角创建反向边框
- java - 尝试在空对象引用android studio上调用虚拟方法'int java.util.ArrayList.size()'
- python-3.x - PyMongo/Python/Airflow - 将 CST 日期/日期时间转换为 UTC 并以 ISO 格式存储在 MongoDB 中?
- events - 从一页到另一页的 Google Analytics(分析)跟踪
- javascript - 从功能组件中传递的道具映射
- typescript - 对象相等比较打字稿。无法将 Object 属性应用于泛型类型
- ruby-on-rails - Active Admin gem ffi 无法在 MacOS 上编译
- webgl - WebGL FBO(实时绘图)
- sql - 查询今天未完成调查的用户并收到错误
- r - 如何将 as_tibble() 格式的时间序列数据转换为 R 中的 as_tsibble() 格式?