概要:1.table特性;2.table的构造;3.table常用函数;4.table遍历;5.table面向对象

原文地址:http://blog.csdn.net/dingkun520wy/article/details/50231603

1.table特性

table是一个“关联数组”,数组的索引可以是数字或者是字符串,所有索引值都需要用 "["和"]" 括起来;如果是字符串,还可以去掉引号和中括号; 即如果没有[]括起,则认为是字符串索引

table 的默认初始索引一般以 1 开始,如果不写索引,则索引就会被认为是数字,并按顺序自动从1往后编;

table 的变量只是一个地址引用,对 table 的操作不会产生数据影响

table 不会固定长度大小,有新数据插入时长度会自动增长

table 里保存数据可以是任何类型,包括function和table;

table所有元素之间,总是用逗号 "," 隔开;

2.table的构造

创建table

t = {}			--定义一个空表
t["jun"] = 6 --字符串key值的属性
t[1] = 1 --数字key值的属性
t.jun = 16 --字符串key值的简写
t.test = {num=28,str="test"} --属性可以是table
print(t.test.num) --输出28
t.testFunction = function() print("函数") end --属性可以是function
t.testFunction() --调用函数
t:testFunction() --同上 --上面的table还可以这么写
t=
{
1,
jun = 6,
test=
{
num = 28,
str = "test",
}
testFunction = function() print("函数") end,
}

3.table常用函数

table.pack(...)

获取一个索引从
1 开始的参数表 table,并会对这个 table 预定义一个字段 n,表示该表的长度

function table_pack(param, ...)
local arg = table.pack(...)
print("this arg table length is", arg.n)
for i = 1, arg.n do
print(i, arg[i])
end
end table_pack("test", "param1", "param2", "param3")

table.concat(table, sep,  start, end)

table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长.

sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数, 但如果要指定靠后的参数, 必须同时指定前面的参数.

lua 中字符串的存储方式与 C 不一样,lua 中的每个字符串都是单独的一个拷贝,拼接两个字符串会产生一个新的拷贝,如果拼接操作特别多,就会影响性能,所以对于密集型的字符并接,table.concat 比用 ".." 连接更高效。

local tbl = {"apple", "pear", "orange", "grape"}

print(table.concat(tbl))

print(table.concat(tbl, "、"))

print(table.concat(tbl, "、", 2))

print(table.concat(tbl, "、", 2, 3))

table.unpack(table, start, end)

用于返回 table 里的元素,参数 start 是开始返回的元素位置,默认是 1,参数 end 是返回最后一个元素的位置,默认是 table 最后一个元素的位置,参数 start、end 都是可选

local tbl = {"apple", "pear", "orange", "grape"}
print(table.unpack(tbl)) local a, b, c, d = table.unpack(tbl)
print(a, b, c, d) print(table.unpack(tbl, 2))
print(table.unpack(tbl, 2, 3))

table.maxn(table)

返回指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0. 此函数不限于table的数组部分.

tbl = {[1] = "a", [2] = "b", [3] = "c", [26] = "z"}
print(#tbl) --3因为26和之前的数字不连续, 所以不算在数组部分内
print(table.maxn(tbl)) --26
tbl[91.32] = true
print(table.maxn(tbl)) --91.32

table.getn(table)

返回table中元素的个数

t1 = {1, 2, 3, 5};
print(getn(t1))
--4

table.insert(table,
pos, value)

用于向
table 的指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.

local tbl = {"apple", "pear", "orange", "grape"}

table.insert(tbl, "watermelon")
print(table.concat(tbl, "、")) table.insert(tbl, 2, "watermelon")
print(table.concat(tbl, "、"))

table.remove(table, pos)

删除并返回table数组部分位于pos位置的元素.
其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起,并且参数 pos 的类型只能是数字 number
类型。

local tbl = {"apple", "pear", "orange", "grape"}
table.remove(tbl, 2)
print(table.concat(tbl, "、")) table.remove(tbl)
print(table.concat(tbl, "、"))

table.sort(table, comp)

用于对 table 里的元素作排序操作,参数
comp 是一个排序对比函数,它有两个参数 param1、param2,如果 param1 排在 param2 前面,那么排序函数返回 true,否则返回 false。参数 comp 可选,缺省 comp 的情况下是对表作升序排序。

local tbl = {"apple", "pear", "orange", "grape"}
local sort_func1 = function(a, b) return a > b end
table.sort(tbl, sort_func1)
print(table.concat(tbl, "、")) local sort_func2 = function(a, b) return a < b end
table.sort(tbl, sort_func2)
print(table.concat(tbl, "、"))
local tbl = {"apple", "pear", "orange", "grape"}
table.sort(tbl)
print(table.concat(tbl, "、"))

table.foreachi(table,
function(i, v))

会期望一个从
1(数字 1)开始的连续整数范围,遍历table中的key和value逐对进行function(i, v)操作

t1 = {2, 4, 6, language="Lua", version="5", 8, 10, 12, web="hello lua"};
table.foreachi(t1, function(i, v) print (i, v) end) ;
--结果1 2
--2 4
--3 6
--4 8
--5 10
--6 12

table.foreach(table, function(i, v))

与foreachi不同的是,foreach会对整个表进行迭代

t1 = {2, 4, 6, language="Lua", version="5", 8, 10, 12, web="hello lua"};
table.foreach(t1, function(i, v) print (i, v) end) ;
--[[
输出结果:
1 2
2 4
3 6
4 8
5 10
6 12
web hello lua
language Lua
version 5
]]

4.table遍历

for key, value in pairs(tbtest) do
print(value)
end

这样的遍历顺序并非是tbtest中table的排列顺序,而是根据tbtest中key的hash值排列的顺序来遍历的。 for key, value in ipairs(tbtest) do
     print(value)
end  
这样的循环必须要求tbtest中的key为顺序的,而且必须是从1开始,ipairs只会从1开始按连续的key顺序遍历到key不连续为止。

5.table面向对象

和编译型的面向对象语言不同,在lua中不存在类的定义这样一个概念,不管是类的定义还是类的实例都需要通过lua table来模拟。

Test = {jun = 0}
function Test.withdraw(self,v)
self.jun = self.jun - v
end
--下面是代码的调用:
a = Test
a.withdraw(a,10)

Lua提供了一种更为便利的语法,即将点(.)替换为冒号(:),这样可以在定义和调用时均隐藏self参数

function Test:withdraw(v)
self.jun = self.jun - v
end
a = Test
a:withdraw(10)

Lua 没有类的概念,不过可以通过元表(metatable)来实现与原型 prototype 类似的功能,而 prototype 与类的工作机制一样,都是定义了特定对象行为。Lua 里的原型特性主要使用元表的
__index 事件来实现,这样当调用对象没定义的方法时,会向其元表的 __index 键(事件)查找。例如有 a 和 b 两个对象,想让 b 作为 a 的原型 prototype,只需要把 b 设置为 a 元表的 __index 值就行:当对象 a 调用任何不存在的成员都会到对象 b 中查找,a 可以拥有或调用 b 的属性或方法,从某种意义上看,b
可以看作是一个类,a 是 b 的对象。

--[[
在这段代码中,我们可以将Account视为class的声明,如Java中的:
public class Account
{
public float balance = 0;
public Account(Account o);
public void deposite(float f);
}
--]]
--这里balance是一个公有的成员变量。
Account = {balance = 0} --new可以视为构造函数
function Account:new(o)
o = o or {} --如果参数中没有提供table,则创建一个空的。
--将新对象实例的metatable指向Account表(类),这样就可以将其视为模板了。
setmetatable(o,self)
--在将Account的__index字段指向自己,以便新对象在访问Account的函数和字段时,可被直接重定向。
self.__index = self
--最后返回构造后的对象实例
return o
end --deposite被视为Account类的公有成员函数
function Account:deposit(v)
--这里的self表示对象实例本身
self.balance = self.balance + v
end --下面的代码创建两个Account的对象实例 --通过Account的new方法构造基于该类的示例对象。
a = Account:new()
--[[
这里需要具体解释一下,此时由于table a中并没有deposite字段,因此需要重定向到Account,
同时调用Account的deposite方法。在Account.deposite方法中,由于self(a对象)并没有balance
字段,因此在执行self.balance + v时,也需要重定向访问Account中的balance字段,其缺省值为0。
在得到计算结果后,再将该结果直接赋值给a.balance。此后a对象就拥有了自己的balance字段和值。
下次再调用该方法,balance字段的值将完全来自于a对象,而无需在重定向到Account了。
--]]
a:deposit(100.00)
print(a.balance) --输出100 b = Account:new()
b:deposit(200.00)
print(b.balance) --输出200

继承

--需要说明的是,这段代码仅提供和继承相关的注释,和类相关的注释在上面的代码中已经给出。
Account = {balance = 0} function Account:new(o)
o = o or {}
setmetatable(o,self)
self.__index = self
return o
end function Account:deposit(v)
self.balance = self.balance + v
end function Account:withdraw(v)
if v > self.balance then
error("Insufficient funds")
end
self.balance = self.balance - v
end --下面将派生出一个Account的子类,以使客户可以实现透支的功能。
SpecialAccount = Account:new() --此时SpecialAccount仍然为Account的一个对象实例 --派生类SpecialAccount扩展出的方法。
--下面这些SpecialAccount中的方法代码(getLimit/withdraw),一定要位于SpecialAccount被Account构造之后。
function SpecialAccount:getLimit()
--此时的self将为对象实例。
return self.limit or 0
end --SpecialAccount将为Account的子类,下面的方法withdraw可以视为SpecialAccount
--重写的Account中的withdraw方法,以实现自定义的功能。
function SpecialAccount:withdraw(v)
--此时的self将为对象实例。
if v - self.balance >= self:getLimit() then
error("Insufficient funds")
end
self.balance = self.balance - v
end --在执行下面的new方法时,table s的元表已经是SpecialAccount了,而不再是Account。
s = SpecialAccount:new{limit = 1000.00}
--在调用下面的deposit方法时,由于table s和SpecialAccount均未提供该方法,因此访问的仍然是
--Account的deposit方法。
s:deposit(100) --此时的withdraw方法将不再是Account中的withdraw方法,而是SpecialAccount中的该方法。
--这是因为Lua先在SpecialAccount(即s的元表)中找到了该方法。
s:withdraw(200.00)
print(s.balance) --输出-100

私密性

私密性对于面向对象语言来说是不可或缺的,否则将直接破坏对象的封装性。Lua作为一种面向过程的脚本语言,更是没有提供这样的功能,然而和模拟支持类与继承一样,我们仍然可以在Lua中通过特殊的编程技巧来实现它,这里我们应用的是Lua中的闭包函数。

--这里我们需要一个闭包函数作为类的创建工厂
function newAccount(initialBalance)
--这里的self仅仅是一个普通的局部变量,其含义完全不同于前面示例中的self。
--这里之所以使用self作为局部变量名,也是为了方便今后的移植。比如,以后
--如果改为上面的实现方式,这里应用了self就可以降低修改的工作量了。
local self = {balance = initialBalance} --这里我们可以将self视为私有成员变量
local withdraw = function(v) self.balance = self.balance - v end
local deposit = function(v) self.balance = self.balance + v end
local getBalance = function() return self.balance end
--返回对象中包含的字段仅仅为公有方法。事实上,我们通过该种方式,不仅可以实现
--成员变量的私有性,也可以实现方法的私有性,如:
--local privateFunction = function() --do something end
--只要我们不在输出对象中包含该方法的字段即可。
return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}
end --和前面两个示例不同的是,在调用对象方法时,不再需要self变量,因此我们可以直接使用点(.),
--而不再需要使用冒号(:)操作符了。
accl = newAccount(100.00)
--在函数newAccount返回之后,该函数内的“非局部变量”表self就不再能被外部访问了,只能通过
--该函数返回的对象的方法来操作它们。
accl.withdraw(40.00)
print(acc1.getBalance())

Lua基础之table详解的更多相关文章

  1. 数据结构基础-Hash Table详解(转)

    理解Hash 哈希表(hash table)是从一个集合A到另一个集合B的映射(mapping). 映射是一种对应关系,而且集合A的某个元素只能对应集合B中的一个元素.但反过来,集合B中的一个元素可能 ...

  2. (转)总结之:CentOS 6.5 MySQL数据库的基础以及深入详解

    总结之:CentOS 6.5 MySQL数据库的基础以及深入详解 原文:http://tanxw.blog.51cto.com/4309543/1395539 前言 早期MySQL AB公司在2009 ...

  3. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  4. 基础拾遗------webservice详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  5. Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例)

    Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑配置文件(pml.xml)(我 ...

  6. python基础之函数详解

    Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...

  7. 【转载】BootStrap表格组件bootstrap table详解

    (转载,来源“脚本之家”,作者不详) 一.Bootstrap Table的引入 关于Bootstrap Table的引入,一般来说还是两种方法: 1.直接下载源码,添加到项目里面来.由于Bootstr ...

  8. 基础知识redis详解--【Foam番茄】

    Redis 学习方式: 上手就用 基本的理论先学习,然后将知识融汇贯通 nosql讲解 为什么要用Nosql 现在都是大数据时代 大数据一般的数据库无法进行分析处理了 至少要会Springboot+S ...

  9. java基础之:详解内部类(转载)

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

随机推荐

  1. IP地址,子网掩码、默认网关,DNS理论解释

    在网上发现的这篇文章写的非常好,有理论有示例. (一)  问题解析 001.   问:  IP地址,子网掩码,默认网关,DNS服务器,有什么区别呀?我知道没有IP地址就不能上网,我也知道没设DNS就不 ...

  2. Git CMD - mv: Move or rename a file, a directory, or a symlink

    命令格式 git mv [-v] [-f] [-n] [-k] <source> <destination> git mv [-v] [-f] [-n] [-k] <so ...

  3. spark RDD的元素顺序(ordering)测试

    通过实验发现: foreach()遍历的顺序是乱的 但: collect()取到的结果是依照原顺序的 take()取到的结果是依照原顺序的 为什么呢???? 另外,可以发现: take()取到了指定数 ...

  4. ArcMap 10.2 crashes during Loading Document launch stage

    问题描述: ArcMap unexpectedly exits during the "Loading Document..." stage on startup. No erro ...

  5. Quartz 第二课 Jobs and Triggers(官方文档翻译)

    The Quartz API IScheduler—与scheduler交互的主要的接口 IJob—这个接口主要定义scheduler执行内容 IJobDetail—用于定义Jobs实例 ITrigg ...

  6. Android 应用程序的组成部分

    Android应用程序由松散耦合的组件组成,并使用应用程序Manifest绑定到一起,应用程序Manifest描述了每一个组件和它们之间的交互方式,还用于制定应用程序元数据.其硬件和平台要求.外部库以 ...

  7. 总是你 2008-3 (献给L之一)

    文/安然 总是你 是梦里的那份最温柔 轻轻碰触 不再敢轻易提及 总是你 是不经意的那份最感动 点点鲜活 从来就没有淡去 时间远走 我轻轻的收起 那段记忆 不再开启 但是 偶尔 偶尔 总是 总是在不经意 ...

  8. VS2005上一个坑:关于pch 的 error C1023

    昨天编译就报错: c1xx : fatal error C1023: ‘UnicodeDebug\ImEngine.pch’ : unexpected error with pch, try rebu ...

  9. poj 3237 Tree

    就是简单的树链剖分,但标记下传的时候一定要 ^1 而不能直接 = 1,我竟然WA在这么逗比的错误上不如一头撞死…… 上代码: #include <cstdio> #include < ...

  10. ssh 私匙登录, 文件rswrst权限

    skill -KILL -u user1  //注销用户 ssh 免密码登录 http://flysnowxf.iteye.com/blog/1567570 (说是防火墙的问题) http://fly ...