b while a & b are arrays or tables
i am a new programmer and started with lua . i want to do the function that array a -b , the following are my program, it didn't work well
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
I have two questions, the first is input:16: '=' expected near 'a' retrun a[i] Y should i changed into retrun =a[i] and what is the differences between them
the second is input:3: attempt to get length of local 'a' (a nil value) what is wrong with this, even if i changed into local lengthA = table.getn(a) there will be input:3: bad argument #1 to 'getn' (table expected, got nil)
The first problem was already answered, but regarding the second it just means that a
at some point of your program execution is nil
(== null
). I was not able to repeat this with your example though.
I am not completely certain what you are trying to achieve, but I recommend that you first create a function that creates a new table that stores the desired result and then iterate that using pairs
(or normal looping). Something like the following:
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
First of all, your indentation is disguising a problem with your balance between for
s and end
s.
What you have is:
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
Also, because you are modifying a
inside the loop, its length becomes smaller and you'll end up accessing it with an invalid index.
Then there's how you use delTwo
's return value.
Here is an explanation on how iterators work in Lua: http://lua-users.org/wiki/IteratorsTutorial
When you write something like for i in <expr>
, <expr>
must return three values: an iterator function, a state object, and an initial value.
Every iteration, the iterator function will be called with the state object and the current value (starting with the initial value in <expr>
). If it returns nil
, the iteration stops, otherwise its return values are assigned to your loop variables, the body of the for
loop is executed, and the iterator function will be called again with the same state object and the new current value, which is the first of your loop variables ( i
in this case).
A (relatively) simple example may help you understand:
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 comes with two iterator generator functions: ipairs
and pairs
. They both take a table and return what is needed for a for
loop to iterate over the values stored in that table.
ipairs
expects a table with numeric keys from 1 to #table
and generates an iterator which will iterate over those indices in order, returning every time the index and the value:
for i, v in ipairs( { 10, 20, 30 } ) do
print("["..i.."] = " .. v)
end
--// Prints:
--// [1] = 10
--// [2] = 20
--// [3] = 30
pairs
takes any kind of table and generates an iterator which returns pairs of key and value, with pairs coming in any order. In this case keys can be anything except nil
, even tables!
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
So, you have two approaches here.
If you want delTwo
to return a table, you must write your for
loop like this:
for idx, element in ipairs(delTwo(a, b)) do
print(element)
end
--// delTwo *must* return a table with correct numeric indices
or like this:
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.
Here's something for you to study. It's a big piece of code, but I hope you can understand it and learn something from 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
This post stands as a testament to how much free time I have in my hands :)
An alternate version which uses 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
Then if you wanted to use different arrays in the same way, just use the setmetatable(x, mt)
where x is the table you want to have the function and it should work.
上一篇: Wireshark解剖器在Lua
下一篇: b而a&b是数组或表格