V语言02基础2数字
a := 123
默认为整.
a := 0x7B b := 0b01111011 c := 0o173
2,8,16进制均可.始终为整型.与形式无关.以_为数字分隔符.
num := 1_000_000 // 1000000 three := 0b0_11 // 0b11 float_num := 3_122.55 // 3122.55 hexa := 0xF_F // 255 oct := 0o17_3 // 0o173
不同类型,这样转:
a := i64(123) b := byte(42) c := i16(12345) //上为整,下为浮 f := 1.0 f1 := f64(3.14) f2 := f32(3.14)
默认浮为f64,就像整默认为整一样.
数组
相同类型元素的集合.
mut nums := [1, 2, 3] println(nums) // `[1, 2, 3]` println(nums[0]) // `1` println(nums[1]) // `2` nums[1] = 5 println(nums) // `[1, 5, 3]`
数组属性:
属性
意思
len
长度,
cap
容量,内存空间,默认自动,可手动优化
mut nums := [1, 2, 3] println(nums.len) // "3" println(nums.cap) // >="3" nums = [] // 空数组 println(nums.len) // "0"
属性只读,用户不可改.
[1, 2, 3]类型为[]整.而["a", "b"]为[]串.
可在首元素显式指定类型如:[byte(16), 32, 64, 128].数组类型不同,编译不过:[1, "a"].
第2种初化语法:
mut a := []int{len: 10000, cap: 30000, init: 3} //指定数组`属性`来初化.
上面创建10000个3,空间保留为30000个元素大小.参数大小,容量,初化可选,大小默认为0,初化默认为相应类型的默认值.默认数值为0,串为"".保证容量>=大小.
arr := []int{len: 5, init: -1} // `arr == [-1, -1, -1, -1, -1]`, arr.cap == 5 // 声明空数组 users := []int{}
置容量,可提升性能,因为不必再分配.
mut numbers := []int{cap: 1000} println(numbers.len) // 0 // 现在附加元素,不会分配 for i in 0 .. 1000 { numbers << i }
for为区间,而<<为压操作符(把C++的废物利用好).
数组元素类型可为:
类型
示例
数字
[]int,[]i64
串
[]string
符文
[]rune
布尔
[]bool
数组
[][]int
构
[]MyStructName
通道
[]chan f64
函数
[]MyFunctionType []fn (int) bool
接口
[]MyInterfaceName
和类型(C++的变量类型)
[]MySumTypeName
泛型
[]T
映射
[]map[string]f64
枚举
[]MyEnumType
别名
[]MyAliasTypeName
线程
[]thread int
引用
[]&f64
共享
[]shared MyStructType
示例,构的和类型来创建处理不同类型点/线数组.
struct Point { x int y int } struct Line { p1 Point p2 Point } type ObjectSumType = Line | Point //这就是传说中的`和类型`,C++的变量类型. mut object_list := []ObjectSumType{} object_list << Point{1, 1}//点 object_list << Line{//线 p1: Point{3, 3}//由点构成的线. p2: Point{4, 4} } dump(object_list)//[和(点),和(线(点,点))]
多维数组
mut a := [][]int{len: 2, init: []int{len: 3}} a[0][1] = 2 println(a) // [[0, 2, 0], [0, 0, 0]] //上为2维,下为3维 mut a := [][][]int{len: 2, init: [][]int{len: 3, init: []int{len: 2}}} a[0][1][1] = 2 println(a) // [[[0, 0], [0, 2], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
数组操作,主要是<<,类似C++的压后.也可附加整个数组.
mut nums := [1, 2, 3] nums << 4 println(nums) // "[1, 2, 3, 4]" //附加数组 nums << [5, 6, 7] println(nums) // "[1, 2, 3, 4, 5, 6, 7]" mut names := ["John"] names << "Peter" names << "Sam" // names << 10 //类型不同,编译不过
用in表示是否在数组中.
names := ["John", "Peter", "Sam"] println(names.len) // "3" println("Alex" in names) // 假
可用println(arr)打印数组,也易这样s := arr.str()转为串.
nums := [1, 2, 3] nums_copy := nums.clone() //这样复制.
过滤映射用.filter()和.map(),
nums := [1, 2, 3, 4, 5, 6] even := nums.filter(it % 2 == 0) println(even) // [2, 4, 6] // filter can accept anonymous functions even_fn := nums.filter(fn (x int) bool { return x % 2 == 0 }) println(even_fn) words := ["你好", "世界"] upper := words.map(it.to_upper()) println(upper) // ["你好", "世界"] //映射也可接受(λ函数) upper_fn := words.map(fn (w string) string { return w.to_upper() }) println(upper_fn) // ["你好", "世界"]
it为过滤/映射内置变量,指代当前元素,it->迭代/它的意思.
.any()和.all()表示数组满足任一/所有.
ums := [1, 2, 3] println(nums.any(it == 2)) //真 println(nums.all(it >= 2)) //假
数组内置方法,其实数组就是C++的向量.
方法
意思
b := a.repeat(n)
重复(a,n)
a.insert(i, val)
i处插入值
a.insert(i, [3, 4, 5])
i处插入多个值
a.prepend(val)
0处插入,前插
a.prepend(arr)
前插数组
a.trim(new_len)
截断长度
a.clear()
清理,不改容量==a.截断(0).
v := a.first()
a[0]
v := a.last()
a[$-1]
v := a.pop()
取尾并弹
a.delete_last()
弹尾
b := a.reverse()
逆向
a.reverse_in_place()
原位逆向
a.join(joiner)
用合并器合并串数组
排序数组
mut numbers := [1, 3, 2] numbers.sort() // 1, 2, 3 numbers.sort(a > b) // 3, 2, 1
用a,b来描述自定义排序.
struct User { age int name string } mut users := [User{21, "张三"}, User{20, "李四"}, User{25, "王五"}] users.sort(a.age < b.age) //按年龄排序 users.sort(a.name > b.name) //按名排序
数组切片
先是索引,增加时切片就复制成新数组了,用..表示.要求右端>=左端.无右则为$,无左,则为0.
nums := [0, 10, 20, 30, 40] println(nums[1..4]) // [10, 20, 30] //这里[1..4]其实是[1,4)左闭右开要注意. println(nums[..4]) // [0, 10, 20, 30] println(nums[1..]) // [10, 20, 30, 40]
V中,切片也是先是引用,增加后实例.与d区别是分配策略.
array_1 := [3, 5, 4, 7, 6] mut array_2 := [0, 1] array_2 << array_1[..3] println(array_2) // `[0, 1, 3, 5, 4]`
切片用最小容量创建,即cap == len.增加大小时,立即重新分配并移动位置,因而与父独立,也叫增长时复制.先是引用,切片增加元素就复制了.不具备引用特点了.
mut a := [0, 1, 2, 3, 4, 5] mut b := a[2..4] b[0] = 7 // `b[0]`引用`a[2]` println(a) // `[0, 1, 7, 3, 4, 5]`//变化了. b << 9 // `b`重新分配,与a独立了. println(a) // `[0, 1, 7, 3, 4, 5]`不变了. println(b) // `[7, 3, 9]`
添加父数组元素,可能/可能不会使其与子切片独立.要看容量.
mut a := []int{len: 5, cap: 6, init: 2} mut b := a[1..4] a << 3 //无分配. b[2] = 13 // 修改了`a[3]` a << 4 //分配a,与b独立了. b[1] = 3 //与`a`无关了. println(a) // `[2, 2, 2, 13, 2, 3, 4]` println(b) // `[2, 3, 13]`
在父/子新分配内存前,则是引用(非独立)关系.在分配内存后,就是独立关系了.
固定大小数组
长度固定,只能原位修改元素.效率更高,占用内存更少,数据在栈上,不想分配在堆上时,用作缓冲.
多数方法定义在普通数组(d的动态数组)上.可用切片转成普通数组:
mut fnums := [3]int{} //固定3 fnums[0] = 1 fnums[1] = 10 fnums[2] = 100 println(fnums) // => [1, 10, 100] println(typeof(fnums).name) // => [3]int fnums2 := [1, 10, 100]! //短初化符号,(注意:可能要改) anums := fnums[0..fnums.len] println(anums) // => [1, 10, 100] println(typeof(anums).name) // => []int
固定数组的切片,会直接复制.所谓固定数组就是D的静态数组,就是C的普通数组.