3 回答

TA貢獻1826條經驗 獲得超6個贊
使用反射包編寫一個適用于任何切片類型的函數:
func unique(src interface{}) interface{} {
srcv := reflect.ValueOf(src)
dstv := reflect.MakeSlice(srcv.Type(), 0, 0)
visited := make(map[interface{}]struct{})
for i := 0; i < srcv.Len(); i++ {
elemv := srcv.Index(i)
if _, ok := visited[elemv.Interface()]; ok {
continue
}
visited[elemv.Interface()] = struct{}{}
dstv = reflect.Append(dstv, elemv)
}
return dstv.Interface()
}
像這樣使用它:
uniqueIntSlice := unique(intSlice).([]int)
在 Go Playground 上運行代碼。

TA貢獻1811條經驗 獲得超5個贊
如何確保此函數適用于(未排序的)空接口切片{}
考慮到空接口{}具有可比性(https://stackoverflow.com/a/54003329/4466350)
因此,要回答您的問題,重寫原始代碼非常簡單
package main
import (
"fmt"
)
func main() {
intSlice := []interface{}{1, 5, 3, 6, 9, 9, 4, 2, 3, 1, 5}
fmt.Println(unique(intSlice))
}
func unique(src []interface{}) []interface{} {
keys := make(map[interface{}]bool)
list := []interface{}{}
for _, entry := range src {
if _, value := keys[entry]; !value {
keys[entry] = true
list = append(list, entry)
}
}
return list
}
https://play.golang.org/p/vW7vgwz9yc1
如果您的問題變成,如何刪除任何切片類型的重復項,請查看其他答案https://stackoverflow.com/a/65191679/4466350

TA貢獻1843條經驗 獲得超7個贊
沒有什么優雅而且很容易出錯,但是您可以使用一個接收兩個interface{}參數的函數,第一個是要過濾的切片,第二個是指向過濾切片的指針,顯然如果第一個參數是 int 切片,則第二個必須是指向 int 切片的指針。
在函數內部,您可以檢查參數的類型并分別處理它們。
package main
import (
"fmt"
)
func unique(slice interface{}, filtered interface{}) error {
// Check for slice of string
if sliceOfString, ok := slice.([]string); ok {
// If slice is slice of string filtered MUST also be slice of string
filteredAsSliceOfString, ok := filtered.(*[]string)
if !ok {
return fmt.Errorf("filtered should be of type %T, got %T instead", &[]string{}, filtered)
}
keys := make(map[string]bool)
for _, entry := range sliceOfString {
if _, value := keys[entry]; !value {
keys[entry] = true
*filteredAsSliceOfString = append(*filteredAsSliceOfString, entry)
}
}
}else if sliceOfInt, ok := slice.([]int); ok {
// If slice is slice of int filtered MUST also be slice of int
filteredAsInt, ok := filtered.(*[]int)
if !ok {
return fmt.Errorf("filtered should be of type %T, got %T instead", &[]string{}, filtered)
}
keys := make(map[int]bool)
for _, entry := range sliceOfInt {
if _, value := keys[entry]; !value {
keys[entry] = true
*filteredAsInt = append(*filteredAsInt, entry)
}
}
} else {
return fmt.Errorf("only slice of in or slice of string is supported")
}
return nil
}
func main() {
intSlice := []int{1,5,3,6,9,9,4,2,3,1,5}
intSliceFiltered := make([]int, 0)
stringSlice := []string{"a", "b", "b", "c", "c", "c", "d"}
stringSliceFiltered := make([]string, 0)
fmt.Println(intSlice)
err := unique(intSlice, &intSliceFiltered) // Very important to send pointer in second parameter
if err != nil {
fmt.Printf("error filtering int slice: %v\n", err)
}
fmt.Println(intSliceFiltered)
fmt.Println(stringSlice)
err = unique(stringSlice, &stringSliceFiltered) // Very important to send pointer in second parameter
if err != nil {
fmt.Printf("error filtering string slice: %v\n", err)
}
fmt.Println(stringSliceFiltered)
}
正如我所說,它并不優雅。我沒有檢查這個是否有錯誤。
它在這里運行。
- 3 回答
- 0 關注
- 154 瀏覽
添加回答
舉報