lua table杂谈

来源:互联网 发布:黄金k线图软件 编辑:程序博客网 时间:2024/06/10 14:04
今天开始学习lua语言,遇到了table这个奇葩的变量类型

类似C语言中的数组,但是又比数组要强大,C语言的数组必须指定元素类型,比如int   x[10] ;double y[10];

C语言定义数组的时候必须指定数组大小,可以使用malloc

C++的数组相对又比较灵活一点儿了,int x[]=new int[];

不能把数组的思想带到lua的table变量类型的理解中来

[plain] view plaincopy
  1. local tbl={  
  2. x=2,  
  3. y=5,  
  4. z=10,  
  5. }  
  6. tbl[1]=4  
  7. print("tbl.x="..tbl.x)  
  8. print(table.getn(tbl))  

输出为- ->2   - ->1

tbl[1]并不是对应的第一个元素,而是新增了一个元素 key值为1 value值为4

并且table.getn()这个lua自带函数只统计以数字为key值的元素个数,所以最后输出为1


看了一下云峰的分析

http://blog.codingnow.com/2005/10/lua_table.html

lua 的整体效率是很高的,其中,它的 table 实现的很巧妙为这个效率贡献很大。

lua 的 table 充当了数组和映射表的双重功能,所以在实现时就考虑了这些,让 table 在做数组使用时尽量少效率惩罚。

lua 是这样做的。它把一个 table 分成数组段和 hash 段两个部分。数字 key 一般放在数组段中,没有初始化过的 key 值全部设置为 nil 。当数字 key 过于离散的时候,部分较大的数字 key 会被移到 hash段中去。这个分割线是以数组段的利用率不低于 50% 为准。 0 和 负数做 key 时是肯定放在 hash 段中的。

string 和 number 都放在一起做 hash ,分别有各自的算法,但是 hash 的结果都在一个数值段中。hash 段采用闭散列方法,即,所有的值都存在于表中。如果hash 发生碰撞,额外的数据记在空闲槽位里,而不额外分配空间存放。当整个个表放满后,hash 段会扩大,所有段内的数据将被重新 hash ,重新 hash 后,冲突将大大减少。

这种 table 的实现策略,首先保证的是查找效率。对于把 table 当数组使用时将和 C 数组一样高效。对于 hash 段的值,查找几乎就是计算 hash 值的过程(其中string 的 hash 值是事先计算好保存的),只有在碰撞的时候才会有少许的额外查找时间,而空间也不至于过于浪费。在 hash 表比较满时,插入较容易发生碰撞,这个时候,则需要在表中找到空的插槽。lua 在table 的结构中记录了一个指针顺次从一头向另一头循序插入来解决空槽的检索。每个槽点在记录 next 指针保存被碰撞的 key 的关联性。

整个来说,这种解决方法是非常不错的。

关于映射表的实现,我前段时间也做过一个别的研究。贴在留言本上:
<a href="http://www.codingnow.com/2004/board/view.php?paster=777&reply=0">树表结合的一种映射表实现</a>
<a href="http://www.codingnow.com/2004/board/view.php?paster=776&reply=0">在 vector , map , list 间取得平衡</a>



再看个例子

Lua代码 

  1. mytable = { 10, ddd = 301213 }  
  2.   
  3. print(mytable[1])  
  4. print(mytable[2])  
  5. print(mytable[3])  


注释: 
1)、 table 中可以出现没有 key 的项,这个时候,lua 会把这个 table 当做一个数组来看待,这个项的key就是它在数组中的下标(从1开始) 

2)、 上例中, mytable[1] 是 10, mytable[2] 是 12, ddd = 30 这项会被跳过。mytable[3] 是 13 

<pre name="code" class="plain">test={"apple",dd=30,"orange"}print(test[2])

输出是 orange

1、在table中可以没有key值,但是必须有value值

2、只有value值得这种称之为list类型,相当于数组类型,数组第一个下标或者说指引为1,不是0

3、上例中“apple” “orange”是按照数组类型来存储的

4、上例中相当于

test={[1]="apple",dd=30,[2]="orange"}print(test[2])
5、下面这种写法是会报错的

test={1="apple",dd=30,2="orange"}print(test[2])

6、猜一下下面的输出是啥?

test={[1]="apple",dd=30,[2]="orange"}print(test[dd])

输出为nil

并没有dd这个数组key值

----------------------------------------

print(test.dd)
上面这种写法输出才是30


-------------------------------------

下面这种写法会报错

test={[1]="apple",[dd]=30,[2]="orange"}print(test.dd)

table中初始化时【】表示按照数组类型来存储,所以key值必须为整数值

上例中【dd】这是非法的

—————————————

test={[1]="apple",[4]="orange",[2]=30}print(test[3])print(table.getn(test))
上例中输出为

-->nil  -->4

即key值为3的元素为nil    但是test表的长度为4.。。还需要研究一下

——————————————

test={[1]="apple",[5]=30,[2]="orange"}print(test[3])print(table.getn(test))
上面的输出为——>nil    ——>2

由于没有key值为3的

但是此时test表的长度为2   说明【5】=30没有存放在数组里面,可能存储在hash表里面







0 0
原创粉丝点击