2012-03-21 4 views
2

Я попросил нескольких человек и искал Google, но не нашел ответа на это; есть ли способ вернуть индекс переменной в таблице в Lua? У меня есть функция обратного вызова, которая возвращает переменную, которая всегда будет частью таблицы. В обратном вызове это называется просто «shape_one», но сама форма будет одной из таблиц форм и будет выглядеть так: Objects.shapes [4].Индекс возврата таблицы в Lua

Если «shape_one» имеет значение Objects.shapes [4], то есть ли способ вернуть 4?

Надеюсь, я был достаточно ясен.

+1

Близко связано с http: // stackoverflow.com/questions/9754285/in-lua-how-do-you-find-out-the-key-an-object-is-stored-in, если не дубликат. – lhf

ответ

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 на слабую клавиатуру. (Скажите мне, если вы хотите, чтобы я расширил этот момент.)

Кстати, вы можете сохранить shape_index автоматически с помощью некоторой металируемой магии. Скажите мне, если вы хотите, чтобы это объяснялось, я обновлю ответ.

+0

Спасибо за ответ, я думаю, так как я, вероятно, не буду иметь слишком много фигур в одном экземпляре (возможно,> 50), я могу просто выполнить ручной поиск. Благодаря! btw Я просто искал слабые столы, но я не уверен, как они помогут мне в этом случае. Просто ради контекста я довольно новый программист, и я работаю над платформером с движком LÖVE. – Refpeuk

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 использует хеширование для обеспечения каждой таблицы действует уникальный ключ и алгоритм использует очень быстро (не итерации по столу, как в случае с Александром Гладышем).

+0

ОК, спасибо - я не уверен, что я сделаю это так или иначе, но зная, что это будет очень полезно, спасибо! – Refpeuk

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']) 

При этом вы должны быть в состоянии получить доступ и изменять значения. Он использует числовые индексы, поэтому вам может понадобиться изменить этот бит, если это не то, что вы хотите. Это позволит вам создавать новые ключи и получать значения с использованием одной переменной; однако это может быть не самая эффективная реализация.