2 回答

TA貢獻1943條經(jīng)驗 獲得超7個贊
一般來說,你無法判斷 backing array 是否在 2 個切片之間共享,因為使用完整的切片表達式,可能會控制結果切片的容量,然后即使在檢查容量時也不會有重疊。
例如,如果您有一個包含 10 個元素的后備數(shù)組,則可能會創(chuàng)建一個僅包含前 2 個元素的切片,其容量可能為 2。并且可能會創(chuàng)建另一個僅包含其最后 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。它們顯然具有相同的后備數(shù)組,但您沒有任何方法可以說明這一點。
編輯:我誤解了這個問題,下面描述了如何判斷 2 個切片(的元素)是否重疊。
對此沒有語言支持,但由于切片有一些后備數(shù)組的連續(xù)部分,我們可以檢查它們元素的地址范圍是否重疊。
不幸的是,從我們不能對它們應用<
and>
運算符的意義上講,指針是無序的(Go 中有指針,但沒有指針算法)。并檢查第一個切片元素的所有地址是否與第二個切片中的任何元素匹配,這是不可行的。
但是我們可以獲得一個指針值(地址)作為uintptr
使用反射包的一種類型,更具體地說是Value.Pointer()
方法(或者我們也可以使用包來做到這一點unsafe
,但reflect
“更安全”),并且uintptr
值是整數(shù),它們是有序的,所以我們可以比較它們。
那么我們可以做的就是獲取切片的第一個和最后一個元素的地址,通過比較它們,我們可以判斷它們是否重疊。
這是一個簡單的實現(xiàn):
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上嘗試一下。

TA貢獻2037條經(jīng)驗 獲得超6個贊
這個想法是,雖然我不認為有一種方法可以找到支持數(shù)組的開頭,但切片的ptr + cap應該 [*] 指向它的結尾。因此,然后比較最后一個指針是否相等,例如:
func?alias(x,?y?nat)?bool?{? ???return?cap(x)?>?0?&&?cap(y)?>?0?&&?&x[0:cap(x)][cap(x)-1]?==?&y[0:cap(y)][cap(y)-1] }
[*] 該代碼包括以下注釋:
注意:別名假定底層數(shù)組的容量永遠不會因 nat 值而改變;也就是說,這段代碼中沒有 3 操作數(shù)切片表達式(或者更糟的是,基于反射的操作具有相同的效果)。
- 2 回答
- 0 關注
- 168 瀏覽
添加回答
舉報