我已经问了好几个人并搜索了谷歌,但还是没有找到答案;有没有办法在Lua中返回表中变量的索引?我有一个回调函数,它返回一个永远是表的一部分的变量。在回调中,它只是被称为" shape_one",但形状本身将是一个形状表,如下所示:Objects.shapes [4]。
如果" shape_one"具有Objects.shapes [4]的值,那么有没有办法返回4?
我希望我足够清楚。
答案 0 :(得分:3)
这是你的情况吗?
local shapes = { }
local function callback(shape_one)
-- ???
end
local the_shape = { is_circle = false }
shapes[4] = the_shape
assert(callback(the_shape) == 4)
shapes[4]
和the_shape
都包含对值的引用,但在Lua中,这两个变量之间没有其他连接。所以,你不能说“表中变量的索引”,你应该说“表中值的索引,匹配变量中的值”。 “匹配”的确切取决于您的情况。在这种情况下,您最有可能寻找引用相等。
请注意,在Lua中,所有表值都是唯一的,因此the_shape ~= { is_circle = false }
(即具有相同内容的新表),但是the_shape == shapes[4]
(两者都指向相同的值)。如果需要,您可以按值比较表,但这是一个单独的主题。
所以,如果你真的想在表中找到值的索引,你必须手动搜索它。要么进行线性搜索:
local function callback(shape_one)
for k, v in pairs(shapes) do
if v == shape_one then
return k
end
end
return nil, "shape not found" -- or maybe call error() here
end
...或缓存所有形状:
local function tflip(t)
local r = { }
for k, v in pairs(t) do
r[v] = k -- overrides duplicate values if any
end
return r
end
local shape_index = tflip(shapes)
local function callback(shape_one)
return shape_index[shape_one] -- will return nil if not found
end
请注意,shape_index
当然会阻止其内容的垃圾收集。假设它的生命周期与shapes
表的生命周期相同并且与它保持同步,这不是问题。如果不是这种情况,您可以将shapes
表配置为弱键。 (如果你想让我扩展这一点,请告诉我。)
答案 1 :(得分:1)
最有效的方法是使用shape_one作为关键:
local shapes = { }
local function callback(shape)
-- if you wanted to remove shape_one from the table:
shapes[shape] = nil
-- or if you want verify it's in there:
print(shapes[shape] ~= nil)
end
local the_shape = { is_circle = false }
shapes[the_shape] = true
callback(the_shape)
for shape, _ in pairs(shapes) do
callback(shape)
end
Lua使用散列来确保每个表都是一个唯一的密钥,它使用的算法非常快(不像在Alexander Gladysh的解决方案中那样遍历表)。
答案 2 :(得分:0)
我知道它用于别的东西,但它也适用于这种情况。
shapes = {} -- Create your table, can be called anything
shapes.r_index = {} -- Holds the number value, i.e. t[1] = 'Foo'
shapes.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(shapes, mt) -- Creates the metatable
shapes[1] = "Circle" -- Set the values
shapes[2] = "Square"
print(shapes[1], shapes[2]) -- And *should* proove that it works
print(shapes['Circle'], shapes['Square'])
shapes[1] = nil
print(shapes[1], shapes[2]) -- And *should* proove that it works
print(shapes['Circle'], shapes['Square'])
有了这个,你应该能够访问和修改这些值。它使用数字索引,因此如果不是您想要的那样,您可能需要更改该位。这将允许您使用一个变量创建新键并获取值;然而,它可能不是最有效的实现。