[✔️]lua for循环

288 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

数值for循环

for init,max/min,setp do
    statement(s) 
end 
  • 例子:
for i = 1, 3, 1 do
    print(i)
end
// 1,2,3

泛型for循环

for ipairs

遇到有key的无法遍历

local t = {
    'A',
    key = 'B'
};
for i, v in ipairs(t) do
    print('i=' .. i .. ', v=' .. v)
end
// i=1, v=A

for pairs

有没有key都可以正常打印

local t = {
    'A',
    key = 'B'
};

for k, v in pairs(t) do
    print('k=' .. k .. ', v=' .. v)
end
// k=1, v=A
// k=key, v=B

其实pairsiparis是lua的一个function,并不是lua的关键字,如果你对lua源码熟悉的话,你就会找到这2个函数的注册地方:

  • 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}, // ipairs
  {"loadfile", luaB_loadfile},
  {"load", luaB_load},
  {"next", luaB_next},
  {"pairs", luaB_pairs}, // pairs
  {"pcall", luaB_pcall},
  {"print", luaB_print},
  {"warn", luaB_warn},
  {"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},
  /* placeholders */
  {LUA_GNAME, NULL},
  {"_VERSION", NULL},
  {NULL, NULL}
};

迭代器

泛型 for 循环通过一个迭代器函数(ipairs、pairs)来遍历所有值,你会发现在好多的编程语言里面都有迭代器这个概念,特别是在c++的stl里面,当我们要操作数据结构时,迭代器是高频使用的,还有js语言里面,forEach等,你都会看到迭代器的身影。

迭代器的产生

无论是序列容器还是关联容器,最常做的操作无疑是遍历容器中存储的元素,而实现此操作,多数情况会选用“迭代器(iterator)”来实现。那么,迭代器到底是什么呢?

我们知道,尽管不同容器的内部结构各异,但它们本质上都是用来存储大量数据的,换句话说,都是一串能存储多个数据的存储单元。因此,诸如数据的排序、查找、求和等需要对数据进行遍历的操作方法应该是类似的。

既然类似,完全可以利用泛型技术,将它们设计成适用所有容器的通用算法,从而将容器和算法分离开。但实现此目的需要有一个类似中介的装置,它除了要具有对容器进行遍历读写数据的能力之外,还要能对外隐藏容器的内部差异,从而以统一的界面向算法传送数据。

这是泛型思维发展的必然结果,于是迭代器就产生了。