python 有没有ipairs ipairs函数

1222人阅读
2015学习笔记(3)
&lua中基础类 & lbaselib.c
&这里面定义的基础函数,函数指针数组;
static const luaL_Reg base_funcs[] = {
{&assert&, luaB_assert},
{&collectgarbage&, luaB_collectgarbage},
{&dofile&, luaB_dofile},
{&error&, luaB_error},
{&getmetatable&, luaB_getmetatable},
{&ipairs&, luaB_ipairs},
{&loadfile&, luaB_loadfile},
{&load&, luaB_load},
#if defined(LUA_COMPAT_LOADSTRING)
{&loadstring&, luaB_load},
{&next&, luaB_next},
{&pairs&, luaB_pairs},
{&pcall&, luaB_pcall},
{&print&, luaB_print},
{&rawequal&, luaB_rawequal},
{&rawlen&, luaB_rawlen},
{&rawget&, luaB_rawget},
{&rawset&, luaB_rawset},
{&select&, luaB_select},
{&setmetatable&, luaB_setmetatable},
{&tonumber&, luaB_tonumber},
{&tostring&, luaB_tostring},
{&type&, luaB_type},
{&xpcall&, luaB_xpcall},
{NULL, NULL}
&这里写下常见的两个用法, ipirs 和 pairs
static int luaB_pairs (lua_State *L) {
return pairsmeta(L, &__pairs&, 0, luaB_next);
&lua.org中文档这样解释到,如果t有__pairs这个元方法,将table作为参数调用它,并且从调用返回第一个3个结果,否则,返回3个值,分别是:next这个方法,该 table,和一个nil所以这个结构:
& & &for k,v in pairs(t) do body end
&将会迭代table中所有的key-value 对
&其中next函数:
static int luaB_next (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2);
/* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
lua_pushnil(L);
&此函数又会调用到int luaH_next (lua_State *L, Table *t, StkId key) 这个主要的函数.(前面blog有介绍)
&2.ipairs:
static int luaB_ipairs (lua_State *L) {
return pairsmeta(L, &__ipairs&, 1, ipairsaux);
&lua.org中文档这样解释到,如果t有__pairs这个元方法,将table作为参数调用它,并且从调用返回第一个3个结果,否则,返回3个值,分别是:iterator这个方法,该table,和一个0 所以这个结构:
& & &for i,v in ipairs(t) do body end
&将会迭代对(1,t[1]),(2,t[2]).......直到第一个整数key不在表中。
&对应函数:
static int ipairsaux (lua_State *L) {
int i = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
/* next value */
lua_pushinteger(L, i);
lua_rawgeti(L, 1, i);
return (lua_isnil(L, -1)) ? 1 : 2;
&这个函数中又有个关键性的函数
&const TValue *luaH_getint (Table *t, int key) &&
&for循环中,pairs 每次得到的时key , value, & &ipairs 是 索引值 和value,&
&通过简单粗略的分析大概明白这两个能用和不能用的情况、
&local test = { 1, 2, 3, 4 }
&for k , v& in ipairs(test) do
& & & print(k , v)
&for i , v in pairs(test) do
& & & print(i , v)
&输出结果都是
local test = {[1] = 1, [2] = 2, [3] = 3, [4] = 4}
for k , v& in ipairs(test) do
&&&& print(k , v)
for i , v in pairs(test) do
&&&& print(i , v)
输出结果: & &&
&(这里请哪位指点下12为什么反了? 我猜是他们通过hash算法取到的主位置的关系)
&local test = {[1] = 1,& [4] = 4}
&for k , v& in ipairs(test) do
& & & print(k , v)
&for i , v in pairs(test) do
& & & print(i , v)
&输出结果是:
&如果test换成
&local test = {& 1,& 2, [3] = 3, [4] = 4}
&输出结果都是
&换成local test = {& ['a'] = 1, ['b'] = 2, [3] = 3, [4] = 4}
&输出结果是
&可见这两个遍历的时候确实是受上面列出的两个主要函数的影响.ipair只能遍历table中数组部分或者下标是数字的hash表部分。而pair就是所有元素通吃。
&local test = {[1] = 1, [2] = 2, [3] = nil,& [4] = 4}
&local test = {[1] = 1, [2] = 2, &[4] = 4}
&这种 ipair会输出
&所以ipair要想所有有值得元素,下标必须是连续的整数,并且value不能有nil,而pairs就不会
&所以这里在实际操作的时候不注意,各种取长度pairs ipairs乱用就会出现奇怪的问题。
& & & 比如上面的table
& & & local test = {1, 2, 3, &4} & &假如是个存储别人对怪物分别的buff伤害,上满了4个,但是这个时候第3个buff失效了,那么有可能就会这么写 &test[3] = nil & 等遍历的时候如果用ipairs或者#遍历,就会发现怪物掉得血量会很奇怪(用#取到的长度是4),明明有长度是4,为什么只有前两个减血的值?
& & &所以为了避免出现这样简单但是奇怪的需要花比较长时间和精力去找错误。建议,像上面这种情况,某个值不用了,就用table.remove删去(这里需要注意在循环中使用remove 的情况,remove该值,后面的值会向前移动一位,导致后面的索引值乱掉,两个解决方案:一个是从后往前遍历表,另一个是从前往后遍历到remove得时候,将移动的i 减回来),不要使用将表中value置为nil.和遍历的时候能用pair遍历尽量用pair
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:28380次
排名:千里之外
原创:44篇
(4)(5)(3)(2)(4)(15)(2)(11)5350人阅读
Luaaaaaaaa...(1)
介于大家目前有些人比较关心 lua table中pairs 和 ipairs的效率问题, 特此研究了一下... 如有不正 还需指出..&首先来看下 lua中table的结构定义:
table中分为2个存储空间, 一个是线性数组空间(TValue *array), 和一个hash空间(Node *node) 当我们使用 pairs 和 ipairs 会产生两种不同的迭代器, 一个仅仅遍历数组, 一个遍历所有的值
所以, 当调用ipairs的时候, 在线性数组中遇到第一个nil时便停止遍历, 不管后面还是否有值, 这点在遍历的时候要格外注意而pairs的迭代器会调用lua_next, lua_next的实现:
这个函数会根据top信息调用luaH_next获取当前table中的下一组键值, 那么关键就在luaH_next中, 来看看这个函数的实现:
我们粗略的可以看到, 这个函数会先计算索引位置, 并根据该位置优先从线性数组中查找, 如果没有找到, 再从hash表中查找, 所以如果用pairs遍历array, 实则和ipairs等效, 并无差异.所以, 由上面的分析, 如果我们明确table中的数据全部存放在线性数组中, 调用ipairs或者pairs均可, 并无太大差异(注意ipairs时中间不要出现nil值, 否则会导致遍历中断), 如果我们明确遍历hash表中的值, 则使用pairs, 其效率会较遍历array中的差 付个简单测试 遍历个array or hash value的效率:
由于使用了os.time() , 只能获取到秒级时间, 故精确度不算太高...
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:64166次
积分:1034
积分:1034
排名:千里之外
原创:38篇
评论:17条
(2)(2)(1)(1)(1)(4)(1)(1)(1)(2)(3)(16)(1)(1)(2)Lua中的table函数库 - 开源中国社区
当前访客身份:游客 [
当前位置:
发布于 日 8时,
lua的table操作的函数
代码片段(1)
1.&[代码][Lua]代码&&&&
一部分的table函数只对其数组部分产生影响, 而另一部分则对整个table均产生影响. 下面会分开说明.
table.concat(table, sep,
start, end)
concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开。除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长.
sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数, 但如果要指定靠后的参数, 必须同时指定前面的参数.
& tbl = {"alpha", "beta", "gamma"}
& print(table.concat(tbl, ":"))
alpha:beta:gamma
& print(table.concat(tbl, nil, 1, 2))
& print(table.concat(tbl, "\n", 2, 3))
table.insert(table, pos, value)
table.insert()函数在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.
& tbl = {"alpha", "beta", "gamma"}
& table.insert(tbl, "delta")
& table.insert(tbl, "epsilon")
& print(table.concat(tbl, ", ")
alpha, beta, gamma, delta, epsilon
& table.insert(tbl, 3, "zeta")
& print(table.concat(tbl, ", ")
alpha, beta, zeta, gamma, delta, epsilon
table.maxn(table)
table.maxn()函数返回指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0. 此函数不限于table的数组部分.
& tbl = {[1] = "a", [2] = "b", [3] = "c", [26] = "z"}
& print(#tbl)
-- 因为26和之前的数字不连续, 所以不算在数组部分内
& print(table.maxn(tbl))
& tbl[91.32] = true
& print(table.maxn(tbl))
table.remove(table, pos)
table.remove()函数删除并返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起.
table.sort(table, comp)
table.sort()函数对给定的table进行升序排序.
& tbl = {"alpha", "beta", "gamma", "delta"}
& table.sort(tbl)
& print(table.concat(tbl, ", "))
alpha, beta, delta, gamma
comp是一个可选的参数, 此参数是一个外部函数, 可以用来自定义sort函数的排序标准.
此函数应满足以下条件: 接受两个参数(依次为a, b), 并返回一个布尔型的值, 当a应该排在b前面时, 返回true, 反之返回false.
例如, 当我们需要降序排序时, 可以这样写:
& sortFunc = function(a, b) return b & a end
& table.sort(tbl, sortFunc)
& print(table.concat(tbl, ", "))
gamma, delta, beta, alpha
用类似的原理还可以写出更加复杂的排序函数. 例如, 有一个table存有工会三名成员的姓名及等级信息:
guild = {}
table.insert(guild, {
 name = "Cladhaire",
 class = "Rogue",
 level = 70,
table.insert(guild, {
 name = "Sagart",
 class = "Priest",
 level = 70,
table.insert(guild, {
 name = "Mallaithe",
 class = "Warlock",
 level = 40,
对这个table进行排序时, 应用以下的规则: 按等级升序排序, 在等级相同时, 按姓名升序排序.
可以写出这样的排序函数:
function sortLevelNameAsc(a, b)
 if a.level == b.level then
  return a.name & b.name
  return a.level & b.level
测试功能如下:
& table.sort(guild, sortLevelNameAsc)
& for idx, value in ipairs(guild) do print(idx, value.name) end
1, Mallaithe
2, Cladhaire
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) ; --等价于foreachi(t1, print)
输出结果:
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) ;
输出结果:
web hello lua
language Lua
table.getn(table)
返回table中元素的个数
t1 = {1, 2, 3, 5};
print(getn(t1))
table.setn(table, nSize)
设置table中的元素个数
开源中国-程序员在线工具:
相关的代码(17)
0回/1250阅
1回/1360阅
开源从代码分享开始
jack_cheng的其它代码推荐这篇日记的豆列
······

我要回帖

更多关于 lua pairs ipairs区别 的文章

 

随机推荐