golang笔记——数组与切片
2016-03-03 19:36
281 查看
一、切片的定义
我们可以从数组(go语言中很少直接使用数组)或者切片来初始化一个新的切片,也可以直接通过 make 来初始化一个所有元素为默认零值的切片。
和其它大多数编程语言类似,Go语言里的这种索引形式也采用了左闭右开区间,包括m~n的第一个元素,但不包括最后那个元素(译注:比如a = [1, 2, 3, 4, 5], a[0:3] = [1, 2, 3],不包含最后一个元素)。这样可以简化我们的处理逻辑。比如s[m:n]这个slice,0 ≤ m ≤ n ≤ len(s),包含n-m个元素。
二、切片的特点
slice 有点类似 C++ 中的 vector,都是可变长数组,有容量的概念(当切片容量不够时,它会以2倍率来扩张),但是也有很多不同,如 slice 是基于数组的(该数组称为底级数组),slice 的长度是从底级数组中取出来的元素个数,容量是底级数组的最大索引与取出元素的最小索引的差值。array 是值类型,但 slice 却是引用类型。
如果修改某个数组的数据,则基于此数组的切片也会发生改变,反之亦然(基于同一数组的多个切片之间也会互相影响)。这与切片的存储结构有关,切片的存储结构是,依次是底层数组的指针、切片长度、切片容量、切片数据。我们知道,当切片的容量发生变量时,会重新分配地址,所以此时切片和原底级数组的关联就会断开,修改不再影响对方,这一点要注意。
切片的删除并没有内置函数,如果需要删除切片 list 的第 k 个元素,我们一般可以通过下面三种方式操作:
1、通过 copy 方式:
2、通过append方式
3、如果该slice不关心删除后元素的排序顺序,可以简单将要删除的元素值设置为最后一个元素值,然后取 [:len(slice)-1] 的子切片就好了
三、切片的常用操作总结
切片的操作比数组复杂一些,因为切片是可变长的,而且有容量的概念。当切片容量不够时,它会以2倍率来扩张。
1、获取切片长度:len(slice)
2、获取切片容量:cap(slice)
3、为切片追加元素:slicename = append(slicename, element1, element2,...)
该函数是可变参函数,可变参部分也可传入另一个切片,形式为 slicename = append(slicename, slicename2...) ,可以参考可变参函数的用法。其实之前我一直疑惑为什么要再赋值给原切片,其实是因为,但append函数调用时,如果切片容量不够的话,会创建一个新的切片变量,这应该也就是为什么要赋值给原切片的原因吧。
4、切片没有提供删除元素的方法,但可以通过子切片的方式来达成此目的,但无法直接的从中间删除元素;也不能从中间插入元素。
5、切片的复制: copy(target_slice, source_slice)
复制切片要保证目标切片有足够长度(注意与容量无关),如果目标切片长度不足,则只复制到目标切片长度的数据,而不会自行改变目标切片长度来填充其它数据。
我们可以从数组(go语言中很少直接使用数组)或者切片来初始化一个新的切片,也可以直接通过 make 来初始化一个所有元素为默认零值的切片。
//1、通过数组来初始化切片 arr := [...]int{1, 2, 3, 4, 5} slice1 := arr[:] // [1,2,3,4,5] slice2 := arr[2:4] // [3,4] slice3 := arr[:4] // [1,2,3,4] slice4 := arr[2:] // [3,4,5] //2、通过切片来初始化切片 slice5 := slice1[3:] //[4,5] //3、直接初始化。可以通过 make 来初始化,格式为 make([]int, len, cap),所有的元素初始化为默认零值;也可以直接初始化。 slice6 := make([]int, 3, 6) // [0,0,0] slice7 := []int{1, 2, 3, 4, 5} // [1,2,3,4,5]
和其它大多数编程语言类似,Go语言里的这种索引形式也采用了左闭右开区间,包括m~n的第一个元素,但不包括最后那个元素(译注:比如a = [1, 2, 3, 4, 5], a[0:3] = [1, 2, 3],不包含最后一个元素)。这样可以简化我们的处理逻辑。比如s[m:n]这个slice,0 ≤ m ≤ n ≤ len(s),包含n-m个元素。
二、切片的特点
slice 有点类似 C++ 中的 vector,都是可变长数组,有容量的概念(当切片容量不够时,它会以2倍率来扩张),但是也有很多不同,如 slice 是基于数组的(该数组称为底级数组),slice 的长度是从底级数组中取出来的元素个数,容量是底级数组的最大索引与取出元素的最小索引的差值。array 是值类型,但 slice 却是引用类型。
func func1(s []int) { s[0] *= 10 //会修改原切片的值 } func func2(s []int) { for _, v := range s { //不会修改原切片的值,因 for ... range 是只读的 v *= 10 } } func func3(s []int) { for i := 0; i < len(s); i++ { //会修改原切片的值 s[i] *= 10 } } func main() { s := []int{1, 2, 3, 4, 5} //func1(s) // 10,2,3,4,5, //func2(s) //1,2,3,4,5, //func3(s) //10,20,30,40,50, for _, v := range s { println(v, ",") } }
如果修改某个数组的数据,则基于此数组的切片也会发生改变,反之亦然(基于同一数组的多个切片之间也会互相影响)。这与切片的存储结构有关,切片的存储结构是,依次是底层数组的指针、切片长度、切片容量、切片数据。我们知道,当切片的容量发生变量时,会重新分配地址,所以此时切片和原底级数组的关联就会断开,修改不再影响对方,这一点要注意。
a := [...]int{1, 2, 3, 4, 5} s1 := a[:] s2 := a[:] s1[0] = 10 print_array(a[:]) // [10,2,3,4,5] 修改切片会影响到底级数组,反之亦然 s2[0] = 20 print_array(s1) // [20,2,3,4,5] 修改切片会影响到基于同一底级数组的切片 s1 = append(s1, []int{6, 7}...) //append 时容量不够时会导致重新分配内存,与原底级数组关系断开 s1[0] = 100 print_array(s1) // [100,2,3,4,5,6,7] print_array(a[:]) //[20,2,3,4,5] print_array(s2) //[20,2,3,4,5] //print_array 为自行封装的格式化输出切片的方法
切片的删除并没有内置函数,如果需要删除切片 list 的第 k 个元素,我们一般可以通过下面三种方式操作:
1、通过 copy 方式:
func remove(slice []int, index int) []int { copy(slice[index:], slice[index+1:]) return slice[:len(slice)-1] }
2、通过append方式
func remove(slice []int, index int) []int { return append(slice[0:k], slice[k+1]...) }
3、如果该slice不关心删除后元素的排序顺序,可以简单将要删除的元素值设置为最后一个元素值,然后取 [:len(slice)-1] 的子切片就好了
func remove(slice []int, i int) []int { slice[i] = slice[len(slice)-1] return slice[:len(slice)-1] }
三、切片的常用操作总结
切片的操作比数组复杂一些,因为切片是可变长的,而且有容量的概念。当切片容量不够时,它会以2倍率来扩张。
1、获取切片长度:len(slice)
2、获取切片容量:cap(slice)
3、为切片追加元素:slicename = append(slicename, element1, element2,...)
该函数是可变参函数,可变参部分也可传入另一个切片,形式为 slicename = append(slicename, slicename2...) ,可以参考可变参函数的用法。其实之前我一直疑惑为什么要再赋值给原切片,其实是因为,但append函数调用时,如果切片容量不够的话,会创建一个新的切片变量,这应该也就是为什么要赋值给原切片的原因吧。
4、切片没有提供删除元素的方法,但可以通过子切片的方式来达成此目的,但无法直接的从中间删除元素;也不能从中间插入元素。
5、切片的复制: copy(target_slice, source_slice)
复制切片要保证目标切片有足够长度(注意与容量无关),如果目标切片长度不足,则只复制到目标切片长度的数据,而不会自行改变目标切片长度来填充其它数据。
相关文章推荐
- [golang note] 错误处理
- golang 接口interface{}、断言、switch type
- 算法代码实现之二分法查找,Golang(Go语言)实现
- ALGO-102 数对 循环语句 数学知识 VIP试题
- ALGO-113 数的统计 VIP试题
- golang笔记——array
- POJ 2940 Wine Trading in Gergovia【贪心】
- 【转】Google推荐的图片加载库Glide介绍
- Mongoose学习参考文档——基础篇
- 解决angular 与django的冲突
- ALGO-81 动态数组使用 普通试题
- <googlehack>看看黑客们是如何用Google搜索的!
- 你应该使用 Django admin 的 9 个理由
- django meta 类的使用方法
- Google Spanner (中文版)
- Google Spanner简介
- udacity google deep learning 学习笔记
- Google推出儿童专用搜索引擎
- 81.You are currently located in Singapore and have connected to a remote database in Chicago.
- Category和Extension