练习1:请编写一个迭代器fromto, 使得如下循环与数值型for等价:
for i in formto(n, m) do
body
end
--[[
for i = 1, 10 do
body
end
]]
是否能以无状态迭代器实现?
解:
-- 数值型for应该是指 for i = n,m,1 do something end ,由 n到m 步长为1
function formto(n, m)
local n = n - 1
return function()
n = n + 1
if n <= m then
return n
end
end
end
for i in formto(2,5) do
print(i)
end
local function iter(m,n)
n = n + 1
if n <= m then
return n
end
end
function formto(n,m)
return iter, m, n-1 -- m 为不可变状态,n - 1 为控制变量初始值
end
for i in formto(2,10) do
print(i)
end
练习2. 向练习1的增加一个步数的参数,并无状态迭代器也实现下
function fromto(n,m,k)
k=k or 1
n=n-k
return function ()
n=n+k
if (k >0 and n >m) or (k < 0 and n <m) then
return nil
end
return n
end
end
for i in fromto(2,6,1) do
print(i) --body
end
local function iter(t,n)
local m = t[1]
local k = t[2]
n = n + k
if (k > 0 and n > m) or (k < 0 and n < m) then
return nil
end
return n
end
function fromto(n,m,k)
return iter, {m,k}, n - k
end
for i in formto(6,2,-1) do
print(i)
end
练习3 请编写一个迭代器uniquewords,该迭代器返回指定文件中没有重复的所有单词(提示:基于 迭代器和泛型for中 allwords的代码,使用一个表来存储已经处理过的所有单词)
function uniquewords(file)
local t={}
local pos=1
for line in io.lines(file) do
local w,e=string.match(line,"(%w+)()",pos)
while w do
pos=e
t[w]=t[w]==nil and 1 or t[w]+1
w,e=string.match(line,"(%w+)()",pos)
end
pos=1
end
return next,t,nil
end
local file = io.read("xxx.lua",r)
for key,value in uniquewords(file)
if value == 1 then
-- 返回次数1的单词
end
end
练习4 请编写一个迭代器,该迭代器可以返回指定字符串中的所有非空字串
local function iter(str,t) --t[1]是front,t[2]是tail
t[1]=t[1] or 1
t[2]=t[2] or 0
::flag::
if t[1]<#str then
if t[2]<#str then
t[2]=t[2]+1
else
t[1]=t[1]+1
t[2]=t[1]
end
local substr=string.sub(str,t[1],t[2])
if string.match(substr,"[%S]+") then --当子串全是空白字符时认为是空子串,不返回
return t,substr
else
goto flag
end
else
return nil
end
end
function substring(str)
return iter,str,{}
end
----------------------------------------------
for _,s in substring("hel l o") do
print(s)
end
练习5 请编写一个真正的迭代器,该迭代器遍历指定集合的所有子集(该迭代器可以使用同一个表来保存所有结果,只需要在每次迭代时改变表的内容即可,不需要为每个子集创建一个新表)
local function iter(tab,index) --index[1]是front,index[2]是tail
index[1]=index[1] or 1
index[2]=index[2] or 0
local temp={}
if index[1]<#tab then
if index[2]<#tab then
index[2]=index[2]+1
else
index[1]=index[1]+1
index[2]=index[1]
end
for i=index[1],index[2] do
temp[#temp+1]=tab[i]
end
return index,temp
else
return nil
end
end
function subtab(tab)
return iter,tab,{}
end
a={1,2,3,4}
for _,t in subtab(a) do
for k,v in pairs(t) do
print(v)
end
print("-------------")
end