b而a&b是数组或表格
我是一个新的程序员,并从lua开始。 我想做一个数组-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'retrun a [i]我应该改变为retrun = a [i],它们之间的区别是什么?
第二个是输入:3:尝试获取局部'a'的长度(一个零值)这是什么问题,即使我改变为本地lengthA = table.getn(a)会有输入:3:错误的参数#1到'getn'(表预计,没有)
第一个问题已经回答了,但对于第二个,那只是意味着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
首先,你的缩进掩饰一个问题,你之间平衡for
S和end
秒。
你有什么是:
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>
写入类似于for i in <expr>
, <expr>
必须返回三个值:一个迭代器函数,一个状态对象和一个初始值。
每次迭代时,将使用状态对象和当前值(从<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
这篇文章是对我有多少空闲时间的证明:)
使用metatables的替代版本
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是你想要的函数,它应该工作。