我是一个新的程序员,从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 ai Y是否应该改为retrun =ai,它们之间的区别是什么
第二个是输入:3:尝试获取本地'a‘( nil值)的长度。这有什么问题,即使我更改为本地lengthA = table.getn (a ),也会有输入:3:'getn’的错误参数#1 (期望的表,得到的是nil)
发布于 2010-10-28 13:41:16
第一个问题已经回答了,但是关于第二个问题,它只是意味着在你的程序执行的某个点上的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发布于 2010-11-02 18:41:34
首先,缩进掩盖了fors和ends之间的平衡问题。
你所拥有的是:
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>必须返回三个值:迭代器函数、状态对象和初始值。
每次迭代时,都会使用状态对象和当前值(从<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] = 30pairs接受任何类型的表,并生成一个迭代器,该迭代器返回键和值对,其中键和值对以任何顺序出现。在这种情况下,键可以是除了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这篇文章证明了我手中有多少空闲时间:)
发布于 2010-11-10 07:01:31
使用元对象的备用版本
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是你想要拥有函数的表,它应该可以工作。
https://stackoverflow.com/questions/4039802
复制相似问题