返回Lua表格的索引位置

我已经问了几个人并在 Google 上搜索过,但没有找到 Lua 中返回变量在表中索引的方法。我有一个回调函数,返回的变量将始终是表的一部分。在回调函数中它只是称为 "shape_one",但形状本身将是形状表中的一个,并且会像这样:Objects.shapes[4]。

如果 "shape_one" 的值为 Objects.shapes[4],那么是否有办法返回 4?

我希望我足够清楚。

原文链接 https://stackoverflow.com/questions/9798294

点赞
stackoverflow用户6236
stackoverflow用户6236

这是你的问题吗?

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"
end

...或者缓存所有的形状:

local function tflip(t)
  local r = {}
  for k, v in pairs(t) do
    r[v] = k --如果有重复值,则覆盖
  end
  return r
end

local shape_index = tflip(shapes)

local function callback(shape_one)
  return shape_index[shape_one] --如果没有找到,则返回 nil
end

请注意,shape_index,当然,会防止其内容被垃圾回收。假设它的生命周期与 shapes 表相同,并且与之保持同步,那么这不是一个问题。如果不是这种情况,请将 shapes 表配置为弱键。 (如果需要,可以告诉我扩展这个问题。)

顺便说一下,你可以借助一些元表技巧自动更新 shape_index。如果你想了解更多信息,请告诉我,我会更新答案。

2012-03-21 06:10:36
stackoverflow用户837856
stackoverflow用户837856

最高效的方法是使用 shape_one 作为键:

local shapes = { }

local function callback(shape)
    -- 如果您想从表中删除 shape_one:
    shapes[shape] = nil
    -- 或者如果您想验证它是否存在:
    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的解决方案那样迭代表)。

2012-03-21 09:06:36
stackoverflow用户319344
stackoverflow用户319344

我知道它被用于其他用途,但它也适用于这种情况。

shapes = {} -- 创建您的表,可以随意命名
shapes.r_index = {} -- 保存数值,即 t[1] = 'Foo'
shapes.r_table = {} -- 保存字符串值,即 t['Foo'] = 1

mt = {} -- 创建元表
mt.__newindex = function (self, key, value) -- 用于创建新索引
    if value == nil then -- 如果您要删除一个条目,则执行以下操作
        if tonumber(key) then -- 检查您是否正在提供数字索引
            local i_value = self.r_index[key] -- 获取相应的字符串索引
            self.r_index[key] = nil -- 删除
            self.r_table[i_value] = nil
        else -- 否则执行与上述相同的操作,但为给定的字符串索引
            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) -- 对于 t[1] = 'Foo'
        self.r_table[value] = key -- 对于 t['Foo'] = 1
    end
end
mt.__index = function (self, key) -- 当您对它们进行索引时,让您返回值
    if tonumber(key) then
        return (self.r_index[key]) -- 对于 t[1] = 'Foo'
    else
        return (self.r_table[key]) -- 对于 t['Foo'] = 1
    end
end

setmetatable(shapes, mt) -- 创建元表

shapes[1] = "Circle" -- 设置值
shapes[2] = "Square"

print(shapes[1], shapes[2]) -- 应该可以证明它有效
print(shapes['Circle'], shapes['Square'])

shapes[1] = nil
print(shapes[1], shapes[2]) -- 应该可以证明它有效
print(shapes['Circle'], shapes['Square'])

使用此方法,您应该可以访问和修改值。它使用数字索引,因此如果这不是您想要的内容,则可能需要更改这一部分。这将允许您创建新键并使用一个变量获取值;但它可能不是最有效的实施方式。

2012-03-21 09:32:38