回到:
table Lua的table数据类型是同时包含数组结构和hash结构的组合体,table中的数组和hash分开存放。
table基础 1 2 3 4 5 a = {} a[1 ] = 10 a["x" ] = "xxx" print (a['yy' ])
访问不存在的元素,其返回值为nil。
除了nil值,所有数据都可以作为table的索引。正因为如此,数值类型和字符串类型的键可能会出现容易混淆的键:
1 2 3 4 5 6 7 a ={} a[1 ]=10 a["1" ]=100 a[1 ] a[1.0 ] a["1" ]
当字符串索引符合标识符规范时,a["xxx"]
可以写成等价的a.xxx
。
1 2 3 4 a = {} a["key" ] = "value" a.key a.1
构造table 构造数组型的table 1 2 3 4 5 6 7 8 9 10 11 12 13 a = {} a[1 ] = "Perl" a[2 ] = "PHP" a[3 ] = "Ruby" a[4 ] = "Lua" a1 = {"Perl" , "PHP" , "Ruby" , "Lua" } print (a1[1 ]) a2 = {[1 ] = "Perl" , [2 ] = "PHP" , [3 ] = "Ruby" , [4 ] = "Lua" } print (a2[1 ])
使用#
获取数组长度:
1 2 a = {"Perl" , "PHP" , "Ruby" , "Lua" } print (#a)
从数值索引1开始直到遇到nil终止的部分属于序列,即序列是数组的一部分,长度为n的索引范围为{1,n}
。
要注意,如果数值索引出现了空隙,长度的计算将不可靠。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 a = {"Perl" , "PHP" , "Ruby" , "Lua" } a[10 ] = "Python" a[11 ] = "Javascript" print (#a) a1 = {} a1[3 ] = "Perl" a1[4 ] = "PHP" a1[5 ] = "Java" print (#a1) a1[1 ] = "Ruby" a1[2 ] = "Lua" print (#a1) a1 = {} a1[2 ] = "Perl" a1[3 ] = "PHP" a1[4 ] = "Java" print (#a1) for i in ipairs (a1) do print (i) end
因table中的数组的特殊性,”长度”的概念并不很容易定义,通过下图可能更好描述一些。
现在table的数组空间共有6个元素,#
计算的结果为4,为什么不计算为6呢?为什么不计算为9呢?别考虑这些,因为是个迷。
1 2 3 4 5 6 7 a = {} for i = 1 ,100 do a[i] = i * 2 end #a for i = 50 ,60 do a[i] = nil end #a for i = 50 ,64 do a[i] = nil end #a
如果真的需要记录数组中的元素个数,可将实际的元素个数保存在该table的hash中。比如上面6个元素,可保存a["__n"] = 6
。
构造hash型的table 1 2 3 4 5 6 7 8 9 10 11 12 13 14 a = {} a["one" ] = 1 a["two" ] = 2 a["three" ] = 3 a1 = {one = 1 , two = 2 , three = 3 } a11 = {one = 1 , two = 2 , three = 3 ,} a2 = {} a2.one = 1 a2.two = 2 a2.three = 3
构造数组、hash混合的table 1 2 3 4 5 6 7 8 9 a = {"perl" ,"php" ,"shell" , one = 1 , two = 2 , three = 3 , "lua" ,"python" , } print (#a) print (a[4 ])
还可以类型嵌套:
1 2 3 4 5 6 7 8 9 a = {"perl" ,"php" ,"shell" , { one = 1 , oneone = 11 }, { two = 2 , twotwo = 22 }, { three = 3 , threethree = 33 }, "lua" ,"python" , } print (a[4 ]) print (a[4 ]["one" ])
通用构造式 更通用的构造方式是[key] = value
方式。
例如:
1 2 3 4 5 a = { ["one" ] = 1 , ["two" ] = 2 , [1 ] = "one" , [2 ] = "two" , }
这种通用构造方式可以构造hash的键值对,且key可以包含特殊符号,也可以以数值作为key构造数组元素。
遍历table 遍历所有元素 使用pairs()遍历table中的所有元素,包括数组和hash,会同时被遍历。注意,pairs()遍历时,只能保证每个元素只出现一次,不保证元素出现的顺序,即使数值索引的顺序也不保证。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 a = {"perl" ,"php" ,"shell" , one = 1 , two = 2 , three = 3 , "lua" ,"python" , } a[10 ] = "java" a[11 ] = "javascript" for k,v in pairs (a) do print (k,v) end for i in pairs (a) do print (i, a[i]) end
遍历序列 序列是从索引1开始到第一个nil元素为止的数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 a = {"Perl" , "Lua" , "Go" , "Shell" } a[6 ] = "Python" a[7 ] = "Java" for i = 1 , #a do print (i, a[i]) end for i in ipairs (a) do print (i, a[i]) end
数组重构成序列 如果想要移除数组的所有间隙,将所有数组元素重组成一个序列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 a = {"perl" ,"php" ,"shell" ,"lua" ,"python" } a[10 ] = "java" a[11 ] = "javascript" a[33 ] = "c" a[44 ] = "go" a[45 ] = "sql" a.idx = {} for i in pairs (a) do if (type (i) == "number" ) then a.idx[ #a.idx+1 ] = i end end table .sort (a.idx)for _,i in pairs (a.idx) do cnt = ( cnt or 0 ) + 1 a[cnt] = a[i] if cnt ~= i then a[i]=nil end end a.idx = nil
table标准库 table标准库只有7个函数:它们全都只适合于序列
1 2 3 4 5 6 7 table.insert table.remove table.move table.concat table.sort table.pack table.unpack
table.concat 用于串联table中序列部分 的元素。
1 2 3 4 5 6 7 8 table.concat (list [, sep [, i [, j]]]) sep: 串联的连接分隔符 i:起使索引,默认为1 j:终止索引,默认为序列的最后一个索引位置 注: (1).索引对应的元素必须存在(即,也不能包含间隙),否则报错 (2).i大于j时,返回空串
例如:
1 2 3 4 5 6 7 8 a = {"perl" ,"php" ,"shell" , one = 1 , two = 2 , three = 3 , "lua" ,"python" , } a[10 ] = "java" a[11 ] = "javascript"
不给任何额外参数时:
指定分隔符:
指定起使、终止的索引位置:
1 2 table .concat (a,"-" ,1 ,3 ) table .concat (a,"-" ,3 )
table.insert 向table的序列部分 插入元素。
1 2 3 4 5 table.insert (list, [pos,] value) 注: (1).省略pos时,表示插入在序列的结尾 (2).插入到指定位置后,序列中该元素后的元素全都后移, 但间隙后的元素不会移动
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 a = {"perl" ,"php" ,"shell" ,"lua" ,"python" } a[10 ] = "java" a[11 ] = "javascript" table .insert (a, "go" )a[6 ] table .insert (a, 7 , "c" )a[7 ] table .insert (a, 8 , "sql" )table .insert (a, 9 , "c++" )table .insert (a, 9 , "lisp" )a[10 ]
table.remove 从table的序列中移除某个元素并返回该元素:
1 2 3 4 5 6 table.remove (list [, pos]) 注: (1).如果不指定pos,则默认移除序列的最后一个元素 (2).移除序列某元素后,其后方元素将前移,但间隙后的元素不受影响 (3).序列无元素可移除时,返回nil
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 a = {"perl" ,"php" ,"shell" ,"lua" ,"python" } a[10 ] = "java" a[11 ] = "javascript" table .remove (a) a[5 ] a[10 ] table .remove (a, 3 ) a[3 ] a[4 ] a[10 ]
table.move 移动table中的元素。
1 2 3 4 5 6 7 8 table.move (a1, f, e, t [,a2]) 注: (1).将table a1中的a[f]到a[e]部分的元素移动到a2的a2[t],a2[t+1]... (2).不指定a2时,a2为a1,即直接在a1中覆盖式移动 (3).被移动元素自身不会被删除,换句话说,不应该称之为移动,而是元素拷贝 (4).返回a2表,但要求a2表已经存在,如果未指定a2,则返回a1表自身 (5).如果将返回值赋值给某变量,则该变量和a2引用同一table
例如:
1 2 3 4 5 6 7 8 9 10 11 a = {"perl" ,"php" ,"shell" ,"lua" ,"python" } a[10 ] = "java" a[11 ] = "javascript" a2 = {} a3 = table .move(a,10 ,11 ,1 ,a2) a2[1 ] == a3[1 ] a2[1 ] = "JAVA" a3[1 ]
table.move()可用于拷贝序列。
1 2 a1 = table .move(a,1 ,#a,1 ,a1)
table.sort 对序列进行排序:
1 table.sort (list [, comp])
原处排序(排序后,原table中元素的顺序发生改变),默认升序排序,comp为可选参数,其为函数,用于指定排序依据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 a = {"perl" ,"php" ,"shell" ,"lua" ,"python" } a[10 ] = "java" a[11 ] = "javascript" a1 = table .move(a,1 ,#a,1 ,a1) table .sort (a)for k,v in ipairs (a) do print (k,v) end table .sort (a1,function (x,y) return #x > #y end )for k,v in ipairs (a1) do print (k,v) end list = {"perl" ,"shell" ,"php" ,"python" ,"lua" } score = { perl = 70 , shell = 66 , php = 69 , python = 69 , lua = 63 , } table .sort (list,function (n1,n2) return score[n1] > score[n2] end )for i in ipairs (list) do print (i,list[i]) end
table.pack 将一系列元素打包成table:
它会返回一个table,该table包含从1开始的序列,以及一个名为”n”的key,其值为被打包参数的数量,也即序列的长度。
1 2 3 4 5 6 7 8 9 10 a = table .pack("a" ,"b" ,"c" ,"d" ,"e" ) for k,v in pairs (a) do print (k,v) end
table.unpack 序列解包:
1 2 3 4 5 table.unpack (list [, i [, j]]) 注: (1).等价于return list[i], list[i+1], ···, list[j] (2).i默认值为1,j默认值为#list
例如:
1 2 3 4 a = {"a" ,"b" ,"c" ,"d" ,"e" ,n=5 } print (table .unpack (a)) print (table .unpack (a,2 ,3 )) print (table .unpack (a,2 ,2 ))
table实现一个双端队列 table实现双端队列非常简单,直接在table中记录first和last两个端点即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function dequeue () return {first = 0 , last = -1 } end function push (l, v) local last = l.last + 1 l.last = last l[last] = v end function unshift (l, v) local first = l.first - 1 l[first] = v l.first = first end function pop (l) local last = l.last if last < l.first then error ("empty queue" ) end l.last = last - 1 local last_v = l[last] l[last] = nil return last_v end function shift (l) local first = l.first if first > l.last then error ("empth queue" ) end l.first = first + 1 local first_v = l[first] l[first] = nil return first_v end