Go语言中操作切片

Go语言中切片不同于数组,数组长度不可变。但是切片的长度是不固定的,可以追加元素。切片是对数组一个连续片段的引用,所以切片是引用类型,因此在传递切片变量时将传递同一个指针,修改切片会影响其他使用该切片的对象。切片在运行时内部表示为$GOROOT\src\runtime\slice.go):

type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

arrary:指向底层数组某元素的指针,该元素也是切片的起始元素

len:切片长度

cap:切片最大容量,cap >= len

在运行时中,每个切片都是runtime.slice结构体类型的一个实例。切片长度可以通过内置函数len()获得,切片容量可以通过内置函数cap()获得。可以通过以下方法创建切片:

make(T, length, capacity)
make(T, length)
[]T{element1, element2, ...}
[]T{}

1.切片的迭代操作

可以用关键字for ... range迭代切片。迭代时会返回两个值,一个是切片元素的索引,一个是切片元素的值的副本

func main() {
	var s = []int{1, 2, 3}

	for _, element := range s { // _ 空标识符,丢弃索引值
		fmt.Printf("element = %d, element_address = %X\n", element, &element)
	}
}

// element = 1, element_address = C0000180C8
// element = 2, element_address = C0000180C8
// element = 3, element_address = C0000180C8
// 运行结果可以看出,元素地址是相同的,它是迭代变量element的地址

迭代切片时要想获取到每个元素的地址,需要使用切片变量和索引:

func main() {
	var s = []int{1, 2, 3}

	for index, element := range s {
		fmt.Printf("element = %d, element_address = %X\n", element, &s[index])
	}
}

// element = 1, element_address = C00001A0F0
// element = 2, element_address = C00001A0F8
// element = 3, element_address = C00001A100
// 从运行结果也可以看出:切片占用了“一段”连续的内存

2.切片删除/追加元素操作

Go语言没有提供用于删除数组和切片的语法,而是利用切片本身的特性来删除或者追加元素。

func main() {
	var s = []int{1, 2, 3}
	var s1 = []int{7, 8, 9}

	// 追加元素
	// [1 2 3 4]
	s2 := append(s, 4)
	// [1 2 3 7 8 9]
	s3 := append(s, s1...)

	// 删除元素
	// [1, 3]
	s4 := append(s[0:1], s[2:]...)
}

3.查找某个元素是否存在于切片中

查找切片中是否存在某个元素需要根据相应的类型逐个对比。

func main() {
	s := []string{"slice", "features", "study", "in", "Go"}
	target1 := "study"
	target2 := "In"

	fmt.Println(isExist(s, target1)) // true
	fmt.Println(isExist(s, target2)) // false
}

func isExist(s []string, target string) bool {
	for _, i := range s {
		if i == target {
			return true
		}
	}
	return false
}

4.查找切片中某元素的索引

通过内置包reflect的VauleOf函数获取切片的值,再通过for循环遍历数组并于给定元素进行比较,如果相等则返回索引。

import (
	"fmt"
	"reflect"
)

func main() {
	s1 := []string{"slice", "features", "study", "in", "Go"}
	s2 := []int{1, 3, 4, 9, 6, 7}

	fmt.Println(findIndex(s1, "Go"))  // 4
	fmt.Println(findIndex(s2, 4))  // 2
}

func findIndex(slice, item interface{}) int {
	s := reflect.ValueOf(slice)
	for i := 0; i < s.Len(); i++ {
		index := s.Index(i)
		if index.Interface() == item {
			return i
		}
	}
	return -1
}

5.查找数组中最大值/最小值

使用for循环对切片进行遍历,找出最大/小值及其索引。

func main() {
	s := []int{121, 4, 354, 22, -44, 324, -245, 133, 101}
	maxValue := s[0]
	maxValueIndex := 0

	for i := 0; i < len(s); i++ {
		if maxValue < s[i] {
			maxValue = s[i]
			maxValueIndex = i
		}
	}

	fmt.Println(maxValue)         // 354
	fmt.Println(maxValueIndex)    // 2
}

6.删除有序数组重复值

对比切片中相邻两个元素AB的值是否相同,如果相同,直到找到元素值不相同的下一个元素C并将C赋值给B。

func main() {
	s := []int{1, 1, 5, 5, 7, 9}
	
	// [1 5 7 9]
	fmt.Println(removeDuplicates(s))
}

func removeDuplicates(s []int) []int {
	if len(s) == 0 {
		return nil
	}
	l, r := 0, 1

	for ; r < len(s); r++ {
		if s[l] == s[r] {
			continue
		}
		l++
		s[l] = s[r]
	}
	return s[:l+1]
}

全部评论

相关推荐

程序员猪皮:看不到八股什么意思
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务