In Lua, how do you find out the key an object is stored in?

人盡茶涼 提交于 2019-11-30 09:23:36

问题


How would you print() out or find out the index of an object?

For example, if I spawned 20 random rock objects on screen into an array RockTable = {};

Like this RockTable[#RockTable + 1] = rock;

And all 20 rocks are displayed on screen how would I find out what key or index each rock has by clicking on them?

I'm using Corona SDK.

Any help would be greatly appreciated.


回答1:


Invert the table:

function table_invert(t)
  local u = { }
  for k, v in pairs(t) do u[v] = k end
  return u
end

You can then use the inverted table to find the index.

I find this function so useful that it goes into my permanent "Lua utilities" libraries.




回答2:


There's another way you can do it, using metamethods. [Edited to allow you to remove values too]

t = {} -- Create your table, can be called anything
t.r_index = {} -- Holds the number value, i.e. t[1] = 'Foo'
t.r_table = {} -- Holds the string value, i.e. t['Foo'] = 1

mt = {} -- Create the metatable
mt.__newindex = function (self, key, value) -- For creating the new indexes
    if value == nil then -- If you're trying to delete an entry then
        if tonumber(key) then -- Check if you are giving a numerical index
            local i_value = self.r_index[key] -- get the corrosponding string index
            self.r_index[key] = nil -- Delete
            self.r_table[i_value] = nil
        else -- Otherwise do the same as above, but for a given string index
            local t_value = self.r_table[key]
            self.r_index[t_value] = nil
            self.r_table[key] = nil
        end
    else
        table.insert(self.r_index, tonumber(key), value) -- For t[1] = 'Foo'
        self.r_table[value] = key -- For t['Foo'] = 1
    end
end
mt.__index = function (self, key) -- Gives you the values back when you index them
    if tonumber(key) then
        return (self.r_index[key]) -- For For t[1] = 'Foo'
    else
        return (self.r_table[key]) -- For t['Foo'] = 1
    end
end

setmetatable(t, mt) -- Creates the metatable

t[1] = "Rock1" -- Set the values
t[2] = "Rock2"

print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])

t[1] = nil
print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])

It's more versatile as you can copy the t value and take it with you; it also means that you only have to play around with the one variable most of the time - hopefully should reduce the likelihood of you trying to access the wrong thing.




回答3:


The simplest way is to add an "index" property to each rock:

RockTable = {}

for i=1,20 do

    local rock
    -- do your thing that generates a new 'rock' object

    rock.index = #RockTable + 1
    RockTable[rock.index] = rock

end

If you use a touch listener method, you can retrieve the rock this way:

function touchListener( event )
    local rock = event.target
    local rockIndex = rock.index
    -- ...
end

It is true that you can maintain a second table with indices, but I find my method cleaner - when it is time to remove things, you only have to worry about one table, the main one.

I have a question though: why do you need to retrieve that index? In most cases, well designed event listener functions are enough, you don't need to "find" your objects. Of course I lack information on what you are trying to do, but it is possible that you are over-complicating things.




回答4:


you could do something like this to save you some trouble of constantly looping over a table to find the index...

RockTable = {}
RockIndicies = {}

for i = 1, 20 do
    idx = #RockTable + 1
    RockTable[idx] = rock
    RockIndicies[rock] = idx
end

then when you need to know the index, you can just use the rock you have to index RockIndices to quickly get it. If you 'delete' a rock, you'd want to make sure to remove it in both places.




回答5:


Unfortunately you'd need to brute the table, to my knowledge. Although, to know that one was clicked, wouldn't you need to be looping them in some way anyway; and therefore already know the index?

Edit

Oh, unless Corona has some sort of callback event for clicking. I've never used it, I've got experience in Lua though.

You could maybe do a backwards reference, like so:

Rocks = {a rock, a rockB, a rockC}
RocksB = {[a rock] = 1, [a rockB] = 2, [a rockC] = 3}

Then just say rockNum = RocksB[rock]

I'm pretty certain that should work but I can't guarantee it, worth a try though.

Edit2

The brute method would look somewhat like:

function getRock(rock)
    for _,v in pairs(rocks) do
        if (v == rock)
            return _
        end
    end
    return "Rock does not exist."
end


来源:https://stackoverflow.com/questions/9754285/in-lua-how-do-you-find-out-the-key-an-object-is-stored-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!