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.

链接地址: http://www.djcxy.com/p/92438.html

上一篇: Wireshark解剖器在Lua

下一篇: b而a&b是数组或表格