- 2020/12/15,Golang 数组操作
-
2020/02/24,Golang 数组 & 切片
-
数组:
[Len]Type{Value...}
- 切片:
[]Type{Value...}
数组声明时可以使用 ...
当作长度,表示自动判断。
数组声明时,可以只初始化其中的部分值。
a := [...]int{2: 1, 4: 2} // [5]int{0, 0, 1, 0, 4}
b := [5]int{1, 2, 3} // [5]int{1, 2, 3, 0, 0}
基本操作
a := [...]int{1, 2, 3}
var b []int
// 新增
b = append(b, 1)
// 删除元素
s = append(s[:index], s[index+1:]...)
// 遍历
for i := range a {
fmt.Println(a[i])
}
for index, value := range a {
fmt.Printf("%v: %v", index, value)
}
for _, value := range a {
fmt.Printf("%v", value)
}
for i := 0; i < len(array); i++ {
fmt.Printf("value: %d\n", array[i])
}
// 判断元素是否存在/获取元素序号
func Index(target int, array []int) int {
for i, v := range array {
if target == v {
return i
}
}
return -1
}
示例
package main
import (
"fmt"
"reflect"
)
func main() {
a := [5]int{1, 3, 5, 7, 9}
fmt.Printf("%s\t%#v\n", reflect.TypeOf(a), a)
// [5]int [5]int{1, 3, 5, 7, 9}
// array => slice
b := a[:] // a[0:len(a)]
fmt.Printf("%s\t%#v\n", reflect.TypeOf(b), b)
// []int []int{1, 3, 5, 7, 9}
// slice => array
// c := ([5]int)(b) // cannot convert b (type []int) to type [5]int
c := (*[5]int)(b) // 切片只能转换成数组指针
fmt.Printf("%s\t%#v\n", reflect.TypeOf(c), c)
// *[5]int &[5]int{1, 3, 5, 7, 9}
// 用类型别名试试:
type NumArr [5]int
c2 := (*NumArr)(b)
fmt.Printf("%s\t%#v\n", reflect.TypeOf(c2), c2)
// *main.NumArr &main.NumArr{1, 3, 5, 7, 9}
// 只能遍历赋值
d := [5]int{}
for index, v := range b {
d[index] = v
}
fmt.Printf("%s\t%#v\n", reflect.TypeOf(d), d)
// 通过 copy 的方法实现 slice2array
e := [5]int{}
copy(e[:], b) // return length of b
fmt.Printf("%s\t%#v\n", reflect.TypeOf(e), e)
}
去重
func Unique(arr []int) []int {
arrLen := len(arr) - 1
for arrLen > 0 {
for i := arrLen - 1; i >= 0; i-- {
if arr[arrLen] == arr[i] {
arr = append(arr[:i], arr[i+1:]...)
break
}
}
arrLen--
}
return arr
}
func UniqueOptimized(arr []int) []int {
uniqueArr := make([]int, 0, len(arr))
uniqueMap := make(map[int]struct{})
for _, num := range arr {
if _, ok := uniqueMap[num]; !ok {
uniqueArr = append(uniqueArr, num)
uniqueMap[num] = struct{}{}
}
}
return uniqueArr
}
// BenchmarkUniqueOriginal-20 135 8658964 ns/op 0 B/op 0 allocs/op
// BenchmarkUniqueOptimized-20 3501 347027 ns/op 285402 B/op 208 allocs/op
可以看到,一个性能好一些(只用 4% 的时间),资源使用多一些。
使用反射
https://blog.csdn.net/youngwhz1/article/details/83026263
func SliceRemoveDuplicate(a interface{}) (ret []interface{}) {
if reflect.TypeOf(a).Kind() != reflect.Slice {
fmt.Printf("<SliceRemoveDuplicate> <a> is not slice but %T\n", a)
return ret
}
va := reflect.ValueOf(a)
for i := 0; i < va.Len(); i++ {
if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) {
continue
}
ret = append(ret, va.Index(i).Interface())
}
return ret
}
func SliceInsert(s []interface{}, index int, value interface{}) []interface{} {
rear := append([]interface{}{}, s[index:]...)
return append(append(s[:index], value), rear...)
}
func SliceInsert2(s *[]interface{}, index int, value interface{}) {
rear := append([]interface{}{}, (*s)[index:]...)
*s = append(append((*s)[:index], value), rear...)
}
func SliceInsert3(s interface{}, index int, value interface{}) bool {
if ps, ok := s.(*[]string); ok {
if val, ok := value.(string); ok {
rear := append([]string{}, (*ps)[index:]...)
*ps = append(append((*ps)[:index], val), rear...)
return true
}
} else if ps, ok := s.(*[]int); ok {
if val, ok := value.(int); ok {
rear := append([]int{}, (*ps)[index:]...)
*ps = append(append((*ps)[:index], val), rear...)
}
} else if ps, ok := s.(*[]float64); ok {
if val, ok := value.(float64); ok {
rear := append([]float64{}, (*ps)[index:]...)
*ps = append(append((*ps)[:index], val), rear...)
}
} else {
fmt.Printf("<SliceInsert3> Unsupported type: %T\n", s)
}
return false
}
func SliceRemove(s []interface{}, index int) []interface{} {
return append(s[:index], s[index+1:]...)
}
func SliceRemove2(s *[]interface{}, index int) {
*s = append((*s)[:index], (*s)[index+1:]...)
}
func SliceRemove3(s interface{}, index int) bool {
if ps, ok := s.(*[]string); ok {
*ps = append((*ps)[:index], (*ps)[index+1:]...)
} else if ps, ok := s.(*[]int); ok {
*ps = append((*ps)[:index], (*ps)[index+1:]...)
} else if ps, ok := s.(*[]float64); ok {
*ps = append((*ps)[:index], (*ps)[index+1:]...)
} else {
fmt.Printf("<SliceRemove3> Unsupported type: %T\n", s)
return false
}
return true
}
func SliceClear(s *[]interface{}) {
*s = append([]interface{}{})
}
func SliceClear2(s *[]interface{}) {
*s = (*s)[0:0]
}
func SliceClear3(s interface{}) bool {
if ps, ok := s.(*[]string); ok {
*ps = (*ps)[0:0]
//*ps = append([]string{})
} else if ps, ok := s.(*[]int); ok {
*ps = (*ps)[0:0]
//*ps = append([]int{})
} else if ps, ok := s.(*[]float64); ok {
*ps = (*ps)[0:0]
//*ps = append([]float64{})
} else {
fmt.Printf("<SliceClear3> Unsupported type: %T\n", s)
return false
}
return true
}
泛型实现
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
tot := len(s) + len(v)
if tot <= cap(s) {
s2 := s[:tot]
copy(s2[i+len(v):], s[i:])
copy(s2[i:], v)
return s2
}
s2 := make(S, tot)
copy(s2, s[:i])
copy(s2[i:], v)
copy(s2[i+len(v):], s[i:])
return s2
}
内置方法 make
make(Type, Len, Cap)
可以用来为 slice
, map
, channel
三种类型初始化(类似:C 语言 (int *)malloc(5)
)。
这里就看 Slice 的情况。
s1 := make([]int, 5)
s2 := make([]int, 5, 10)
// s2[8] = 1 // panic: runtime error: index out of range [8] with length 5
s2 = append(s2, 1)
如果有预留空间,append
的时候可以不用重新分配内存并遍历赋值。
如果切片有扩容的需要,就最好采用 make
来初始化。
如果不指定容量,则切片的容量和长度将相等。