Как проверить, содержит ли таблица элемент в Lua?

есть ли способ проверить, содержит ли таблица значение ? У меня есть своя (наивная) функция, но мне было интересно, существует ли для этого что-то "официальное"? Или что-то более эффективное...

function table.contains(table, element)
  for _, value in pairs(table) do
    if value == element then
      return true
    end
  end
  return false
end

кстати, основная причина, по которой я использую эти функции, - использовать таблицы как наборы, т. е. без повторяющихся элементов. Есть что-то еще, что я мог бы использовать ?

4 ответов


вы можете поместить значения в качестве ключей таблицы. Например:

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 к interjay.


Я не могу придумать другой способ сравнения значений, но если вы используете элемент набора в качестве ключа, вы можете установить значение на что угодно, кроме нуля. Затем вы получаете быстрый поиск без необходимости поиска по всей таблице.


Я знаю, это старый пост, но я хотел добавить что-то для потомков. Простой способ решения проблемы, которая у вас есть, - сделать другую таблицу, значение для ключа.

ie. у вас есть 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

затем вы можете запросить новую таблицу, чтобы узнать, имеет ли она ключ "элемент". Это предотвращает необходимость перебора всех значений другой таблицы.

если получится что вы не можете использовать "элемент" в качестве ключа, потому что это не строка, например, затем добавьте контрольную сумму или "toString" на нем, например, а затем используйте это как ключ.

почему вы хотите это сделать? Если ваши таблицы очень большие, количество времени для итерации по каждому элементу будет значительным, что не позволит вам делать это очень часто. Дополнительные накладные расходы памяти будут относительно небольшими, так как они будут хранить 2 указателя на один и тот же объект, а не 2 копии одного и того же объекта. Если ваши таблицы очень малы, то это будет иметь гораздо меньшее значение, infact это может быть даже быстрее итерации, чем иметь другой Поиск Карты.

формулировка вопроса предполагает, что у вас есть большое количество элементов для рассмотрения.