我是一名新程序员并以lua开始。我想做数组a -b的功能,以下是我的程序,它运行不正常
function delTwo (a ,b)
local i = 0
local lengthA = #a
local lengthB = #b
for i = 1 ,lengthA do
for j =1 , lengthB do
if a[i]==b[j] then
a[i] = nil
end
end
for i = 1 , lengthA do
if a[i]~= nil then
retrun a[i]
end
end
end
end
a = {10, 20, 30}
b={11,20,122}
for element in delTwo (a ,b) do
print(element)
end
我有两个问题,第一个是输入:16:'='预计在'a'附近 后退a [i] Y我应该改成retrun = a [i] 他们之间有什么区别
第二个输入:3:尝试获取本地'a'的长度(零值) 这有什么问题,即使我改成了本地长度A = table.getn(a) 将有输入:3:错误的参数#1到'getn'(表格预期,得到零)
答案 0 :(得分:2)
第一个问题已经得到解答,但就第二个问题而言,这只意味着a
在程序执行的某个时刻nil
(== null
)。不过,我无法用你的例子重复这个。
我不完全确定您要实现的目标,但我建议您首先创建一个函数,创建一个存储所需结果的新表,然后使用pairs
(或正常循环)进行迭代。如下所示:
function delTwo(a, b)
local result = {}
--# Logic here.
--# Use result[#result + 1] = ... to insert values.
return result
end
for k, v in pairs(delTwo(a,b)) do print(k, v) end
答案 1 :(得分:2)
首先,你的缩进是在掩盖一个问题
在for
和end
s之间保持平衡。
你拥有的是:
function delTwo (a ,b)
local i = 0
local lengthA = #a
local lengthB = #b
for i = 1, lengthA do
for j = 1, lengthB do
if a[i] == b[j] then
a[i] = nil
end
end
for i = 1, lengthA do --// Iterating i while iterating i. Bad things happen!
if a[i] ~= nil then
return a[i]
end
end
end
end
另外,因为你在循环中修改a
,它的长度
变小了,你最终会用无效索引访问它。
然后就是你如何使用delTwo
的返回值。
以下解释了迭代器在Lua中的工作原理: http://lua-users.org/wiki/IteratorsTutorial
当你写for i in <expr>
之类的内容时,<expr>
必须返回
三个值:迭代器函数,状态对象和初始值。
每次迭代时,都会使用state对象调用迭代器函数
和当前值(从<expr>
中的初始值开始)。
如果返回nil
,则迭代停止,否则返回值
分配给你的循环变量,执行for
循环的主体,
并使用相同的状态对象再次调用迭代器函数
新的当前值,这是第一个循环变量
(在这种情况下为i
)。
一个(相对)简单的例子可以帮助您理解:
local state = {}
state["toggle"] = true
function iterator_func(state, prev_i)
--// Calculate current value based on previous value
i = prev_i + 1
--// Stop iteration if we've had enough
if i > 10 then
return nil
end
local msg
if state["toggle"] then
msg = "It's on!"
state["toggle"] = false
else
msg = "It's off!"
state["toggle"] = true
end
return i, i*2, i*3, msg
end
--// Notice the initial value is 0, the value *before* our first iteration
for i, double, triple, msg in iterator_func, state, 0 do
print(tostring(i)..", "
..tostring(double)..", "
..tostring(triple)..", "
..tostring(msg))
end
--// Prints:
--// 1, 2, 3, It's on!
--// 2, 4, 6, It's off!
--// ...
--// 10, 20, 30, It's off!
Lua带有两个迭代器生成器函数:ipairs
和pairs
。
它们都采用表格并返回for
循环迭代所需的内容
超过该表中存储的值。
ipairs
需要一个包含数字键的表,从1到#table
和
生成一个迭代器,它将按顺序迭代这些索引,
每次返回索引和值:
for i, v in ipairs( { 10, 20, 30 } ) do
print("["..i.."] = " .. v)
end
--// Prints:
--// [1] = 10
--// [2] = 20
--// [3] = 30
pairs
接受任何类型的表并生成一个返回成对的迭代器
密钥和价值,对以任何顺序排列。
在这种情况下,键可以是除nil
之外的任何内容,甚至是表格!
aKey = {}
t = { ["First"] = 10, [2.0] = 20, [aKey] = 30 }
for k, v in pairs(t) do
print("["..tostring(k).."] = " .. tostring(v))
end
--// Prints something like:
--// [table: 0x95860b0] = 30
--// [First] = 10
--// [2] = 20
所以,你有两种方法。
如果您希望delTwo
返回一个表,则必须像这样编写for
循环:
for idx, element in ipairs(delTwo(a, b)) do
print(element)
end
--// delTwo *must* return a table with correct numeric indices
或者像这样:
for _, element in pairs(delTwo(a, b)) do
print(element)
end
--// Conventionally, you use _ as a variable name if you plan to just ignore it.
这是你要学习的东西。 这是一段很大的代码,但我希望你能理解它并从中学到一些东西。
--//////////////////////////////////////////////////////////////////////////
--//
--// APPROACH #1
--//
--//
--// This function modifies table a in place,
--// removing elements that are also found in b
--//
local function delTwo_1(a, b)
local lengthB = #b
--// a's length may change if we remove an element from it,
--// so iterate over b and recalculate a's length every iteration.
for j = 1, lengthB do
local lengthA = #a
for i = 1, lengthA do
if a[i] == b[j] then
table.remove(a, i)
--// Don't use " a[i] = nil ".
--// This will just leave you with a nil element in the "middle"
--// of the table, and as it happens ipairs() stops
--// at the first nil index it finds.
--// So:
--// a = { [1] = 10, [2] = 20, [3] = 30}
--// a[2] = nil
--// -- a is now { [1] = 10, [2] = nil, [3] = 30 }.
--//
--// -- ipairs(a) will now return (1, 10) and then stop.
--//
--// -- pairs(a) will return both (1, 10) and (3, 30)
end
end
end
--// Return table a if you want,but it's been modified "outside" as well
return a
end
--//////////////////////////////////////////////////////////////////////////
--//
--// APPROACH #2
--//
--//
--// This function calculates the difference between two tables,
--// without modifying any of them.
--// It will be used in our iterator generator.
--//
local function tableDiff(a, b)
local res = {}
for i = 1, #a do
local skip = false
for j = 1, #b do
if a[i] == b[j] then
skip = true
break
end
end
if not skip then
res[#res+1] = a[i]
end
end
return res
end
--//
--// This function is an iterator generator.
--// It returns an iterator function, a state object and an initial value
--//
local function delTwo_2(a, b)
--// Some preliminary calculations...
local res = tableDiff(a, b)
--// We don't really need state in this case, because we could
--// refer directly to our res variable inside our iterator function,
--// but this is just for demonstration purposes.
local state = {}
state["result"] = res
local function iterator(state, key)
local result = state["result"]
--// Our key is a numeric index, incremented every iteration
--// before anything else (that's just how it works)
key = key + 1
if key > #result then
--// If key is greater than our table length,
--// then we already iterated over all elements.
--// Return nil to terminate.
return nil
end
local element = result[key]
--// Just because we can...
local msg = "We're at element "..key
return key, element, msg
end
local initialKey = 0 --// We start "before" index 1
return iterator, state, initialKey
end
do
--// TESTS
do
--// TESTING APPROACH #1
a = {10, 20, 30}
b = {11, 20, 122}
print "******************* delTwo_1 *******************"
print "Here's delTwo_1's result:"
--// Table a is modified in place
delTwo_1(a, b)
for i, element in ipairs(a) do
print("["..i.."] = "..tostring(element))
end
print()
print "Here's a after delTwo_1:"
for i, element in ipairs(a) do
print("["..i.."] = "..tostring(element))
end
end
print()
print()
do
--// TESTING APPROACH #2
a = {10, 20, 30}
b = {11, 20, 122}
print "******************* delTwo_2 *******************"
print "Here's delTwo_2's result:"
--// Notice how this compares to what
--// is returned by our iterator function
for idx, element, msg in delTwo_2(a, b) do
print(tostring(element) .. " (Msg: "..msg..")")
end
print()
print "Here's a after delTwo_2:"
for i, element in ipairs(a) do
print("["..i.."] = "..tostring(element))
end
end
end
这篇文章证明了我手中有多少空闲时间:)
答案 2 :(得分:1)
使用元表的替代版本
local mt = { --// Just creates a metatable base
__sub = function (a, b) --// Function is the same as Zecc just formatted differently
local lengthB = #b
for j = 1, lengthB do
local lengthA = #a
for i = 1, lengthA do
if a[i] == b[j] then table.remove(a, i) end
end
end
return a
end
}
a = {10, 20, 30} --// Same arrays
b = {11, 20, 122}
setmetatable(a, mt) -- //Use this to give the arrays the __sub function
setmetatable(b, mt)
c = a - b --// Then you can use the maths operator on it
for k, v in ipairs(c) do --// printing them out gives the same as above
print(k, v)
end
然后,如果你想以相同的方式使用不同的数组,只需使用setmetatable(x, mt)
,其中x是你想拥有该函数的表,它应该可以工作。
答案 3 :(得分:1)
问题就像设置差异一样,下面的函数准备一个可能值的dict从数组b中删除,并在遍历时检查数组a是否包含它。如果更改make代替数组a或返回一个新的,则该函数具有可选的inplace标志。
function arrayDiff(a,b,inplace)
inplace = inplace~=false -- default inplace
local ret = inplace and a or {}
local toRemove = {} -- a dict for value to remove
for i=1,#b do toRemove[b[i]]=true end
local nxtInsert = 0
local aLen = #a
for i=1,aLen do
local value = a[i]
if not toRemove[value] then
nxtInsert = nxtInsert + 1
ret[nxtInsert] = value
end
end
if inplace then
for i=nxtInsert+1,aLen do ret[i]=nil end
end
return ret
end
答案 4 :(得分:0)
以下是我的函数实现,它执行以下操作: 1.从A中的元素x中减去,从B中减去元素y(如果y存在)
function arrDel(a,b)
local result = {}
for i = 1, #a, 1 do
result[i] = a[i] - ( b[i] or 0) -- 'or 0' exists to cope with if #b < #a
end
return result
end
此代码创建并填充一个名为result的表,该表是从a中减去b的“结果”。在lua中存在两种类型的for循环:数字和泛型。上述函数中的循环使用数字类型的循环。当它包含的代码块需要执行已知次数或索引以找到循环使用的值是微不足道时,应该使用此循环。
sytanx如下:
for counter = initial, final, increment do
body
end
增量是可选的,默认为1。
为了演示另一种类型的循环,这个小函数打印出一个非常简单的表:
function tprint(t)
local res = {}
for _,v in ipairs(t) do
res[#res+1] = v
end
print("{"..table.concat(res,",").."}")
end
此处使用泛型for(使用'in'关键字)。通用允许轻松遍历复杂对象。例如,假设一个对象包含用户的记录,但是记录存储在VIP,管理员,访客等部分中......并且您想要覆盖所有用户。您可以编写一个函数,然后在泛型中使用该函数,使用类似于此的表达式轻松完成此操作:
for user in object.traverseUsers() do
body
end
这些迭代器的实现超出了这个问题的答案范围,但可以在这里找到一个很好的解释Generic For (PIL)
答案 5 :(得分:0)
如果有可能会给出除表之外的其他内容,但您仍希望保持代码运行,请使用此
local lengthA = a and #a or 0
local lengthB = b and #b or 0
不是必需的,只是一点信息;无需说
if a[i] ~= nil then
你可以这样做:
if a then