3.10 数组
Ruby | Javascript | Go | Lua | |
---|---|---|---|---|
起始索引 | 0 | 0 | 0 | 1 |
倒序索引 | arr[-1] |
不支持 | 不支持 | 不支持 |
索引越界 | nil | undefined | panic | nil |
长度 | length size |
属性 length |
内置函数len() |
# table.getn(t) |
长度可写 | 不支持 | arr.length = 3 |
不支持 | 不支持 |
追加 | Array#<< push |
arr.push([element1[, ...[, elementN]]]) |
func append(slice []Type, elems ...Type) []Type |
table.insert (list, [pos,] value) |
连接 | Array#+(other) concat(ary1,ary2...) |
concat(ary1,ary2...) |
append(slice1, slice2...) |
自行实现 |
数组字面量容器 | [] |
[] |
{} |
具体数组类型{} |
1. Ruby
无空格短字符串组成的数组, 有额外的表达方式:
words = %w[hello ruby]
Ruby Array的语法糖很多, 举几个例子:
[1,2] * 3 # [1,2,1,2,1,2] [1,2] & [2,3] # [3] [1,2] | [2,3] # [1,2,3]
2. Javascript
长度可写
这算是几门语言中, Javascript比较特殊的地方:
let arr = [1, 2, 3];
arr.length = 2; //[1, 2]
ES6 扩展
ES6 对Array进行了一系列扩展, 介绍几个:
find 和 findIndex
Array.prototype.find(callback[, thisArg])
[1, 4, -3, 10].find((n) => n < 0)
// -3
还可以接受三个参数:
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
可选参数thisArg, 用来绑定回调函数的this对象.
类似的方法还有Array.prototype.findIndex(Array.prototype.findIndex())
entries(), keys()和values()
Array.prototype 新增了三个方法, entries keys 和 values 都可以返回一个遍历器对象, 分别可以遍历键名, 键值, 以及键值对.
3. Go
Array
数组是一个值类型(value type)
所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作
如果将数组作为函数的参数类型, 则在函数调用时该参数将发生数据复制. 因此, 在函数体中无法修改传入的数组的内容, 因为函数内操作的只是所传入数组的一个副本, 如需修改, 可以传递数组指针或者数组的切片.
长度是数组类型的一部分
定义类型时居然要带上长度:
func modify(array [10] int) {...
数组长度在定义后就不可更改(len 不可变, 不能使用append方法, 但是内部数据可以变)
数组 len 和cap等值
初始化:
a := [5] int{1,2,3} b := [...]int{1,2,3,4} //自动长度 c := [...]int{1: 10, 2: 20, 4: 40} //[0 10 20 0 40]
比较:
如果元素支持
==
!=
数组也支持, 如果两个数组的对应元素比较都相等, 则数组比较为相等, 否则为不等.如果元素不支持比较, 则数组比较会报错.
数组的指针和数组第一个元素的指针相同
数组指针可以用于操作元素:
&someArray[1]
slice
切片并非数组指针, 它有指向底层数组的独立数据结构, 限定读写范围
切片访问起始索引从0开始, 超过index的读写会报错: 'index out of range'
通过已有数组创建切片:
- len, cap不能超出原始数组的范围, cap不能小于len
someArray[开始索引:结束索引:cap索引]
, 这种数组必须是addressable的, 比如map中的数组就不是addressablecap索引
可以省略, 右开开始索引:结束索引
左闭右开- len: 可读元素,
结束索引-开始索引
通过切片创建切片: 受原始切片cap影响
切片修改对所有关联切片可见
初始化变量:
var a []int
没初始化的slice零值是nilmake([]int, len, cap)
len必要, cap可省, 该数据不为nil不支持比较运算
slice 可以取地址, 但是地址和第一个元素的地址是不同的, slice的地址不能支持索引操作, 如
(&someslice)[0]
报错append(someslice, item ...Type)
- 如果是基于底层数组, 不能超过底层数组的len
- 如果超过本身的cap, 重新分配底层数组, cap将double(不精确), 因此性能有影响
- 返回新的slice, 新旧slice指针不同, len, cap也是独立的, 但是底层数组相同
4. Lua
Lua 使用table来实现数组, Lua 中叫做列表(list), 索引从1开始.
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
table 中如果有nil, table的长度是不确定的. 因此在使用Lua list时, 尽量避免空洞nil.
如果要删除数组中指定位置的值, 建议不要直接赋值nil, 这样会造成空洞, 推荐使用table.remove (list [, pos])
, table.remove 在删除元素后, 会把后置的元素依次前移, 避免空洞.