Как проверить, содержит ли таблица элемент в Lua?
Вопрос
Существует ли способ проверить , содержит ли таблица значение ?У меня есть своя (наивная) функция, но мне было интересно, существует ли для этого что-то "официальное"?Или что-то более эффективное...
function table.contains(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
Кстати, основная причина, по которой я использую эти функции, заключается в использовании таблиц как наборов, то есть без повторяющихся элементов.Есть ли что - то еще , что я мог бы использовать ?
Решение
Вы можете поместить значения в качестве ключей таблицы.Например:
function addToSet(set, key)
set[key] = true
end
function removeFromSet(set, key)
set[key] = nil
end
function setContains(set, key)
return set[key] ~= nil
end
Есть более полнофункциональный пример здесь.
Другие советы
Учитывая ваше представление, ваша функция настолько эффективна, насколько это возможно. Конечно, как отмечали другие (и как это практикуется на языках старше Lua), решение вашей реальной проблемы заключается в изменении представления.Когда у вас есть таблицы и вам нужны наборы, вы превращаете таблицы в наборы, используя элемент set в качестве ключа и true
как значение.+1 к междометию.
Я не могу придумать другого способа сравнения значений, но если вы используете элемент набора в качестве ключа, вы можете установить значение любым, кроме nil.Тогда вы получаете быстрый поиск без необходимости выполнять поиск по всей таблице.
Я знаю, что это старый пост, но я хотел добавить кое-что для потомков.Самый простой способ решить возникшую у вас проблему - создать другую таблицу, имеющую значение для ключа.
т. е.у вас есть 2 таблицы, которые имеют одинаковое значение, одна указывает в одном направлении, другая - в другом.
function addValue(key, value)
if (value == nil) then
removeKey(key)
return
end
_primaryTable[key] = value
_secodaryTable[value] = key
end
function removeKey(key)
local value = _primaryTable[key]
if (value == nil) then
return
end
_primaryTable[key] = nil
_secondaryTable[value] = nil
end
function getValue(key)
return _primaryTable[key]
end
function containsValue(value)
return _secondaryTable[value] ~= nil
end
Затем вы можете запросить новую таблицу, чтобы узнать, есть ли в ней ключевой "элемент".Это избавляет от необходимости перебирать каждое значение другой таблицы.
Если выяснится, что на самом деле вы не можете использовать 'element' в качестве ключа, потому что это, например, не строка, то добавьте контрольную сумму или tostring
на нем, например, а затем используйте это в качестве ключа.
Почему ты хочешь это сделать?Если ваши таблицы очень большие, то время на перебор каждого элемента будет значительным, что не позволит вам делать это очень часто.Дополнительные затраты памяти будут относительно невелики, так как в ней будут храниться 2 указателя на один и тот же объект, а не 2 копии одного и того же объекта.Если ваши таблицы очень маленькие, то это будет иметь гораздо меньшее значение, фактически итерация может быть даже быстрее, чем другой поиск по карте.
Однако формулировка вопроса убедительно свидетельствует о том, что вам предстоит разобраться с большим количеством вопросов.