¿Cómo comprobar si una tabla contiene un elemento en Lua?
Pregunta
¿Hay un método para comprobar si una tabla contiene un valor? Tengo mi propia función (ingenuo), pero me preguntaba si algo existe "oficial" para eso? O algo más eficiente ...
function table.contains(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
Por cierto, la razón principal que estoy usando estas funciones es utilizar tablas como conjuntos, es decir, sin elementos duplicados. ¿Hay alguna otra cosa que pueda usar?
Solución
Usted puede poner los valores como claves de la tabla. Por ejemplo:
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
Hay un ejemplo más plenamente las funciones de aquí .
Otros consejos
Dada su representación, su función es tan eficiente como se puede hacer. Por supuesto, como se ha señalado por otros (y como se practica en idiomas mayores de LUA), la solución a su problema real es cambiar la representación. Cuando tiene tablas y desea conjuntos, que convertir las tablas en conjuntos utilizando el elemento del registro como la clave y true
como el valor. 1 a interjay.
No puedo pensar en otra forma de comparar los valores, pero si se utiliza el elemento del conjunto como la clave, se puede establecer el valor distinto de cero nada. A continuación, se obtiene búsquedas rápidas sin tener que buscar en toda la mesa.
Sé que esto es una entrada antigua, pero quería añadir algo para la posteridad. La forma más sencilla de manejar el problema que tiene es hacer otra tabla, del valor de la clave.
ie. usted tiene 2 tablas que tienen el mismo valor, uno apuntando en una dirección, una apuntando hacia el otro.
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
A continuación, puede consultar la nueva tabla para ver si tiene la clave 'elemento'. Esto evita la necesidad de recorrer todos los valores de la otra tabla.
Si resulta que no se puede utilizar realmente el 'elemento' como una clave, porque no es una cadena, por ejemplo, a continuación, añadir una suma de comprobación o tostring
en él, por ejemplo, y luego usar eso como la clave.
¿Por qué quieres hacer esto? Si las tablas son muy grandes, la cantidad de tiempo de repetición de cada elemento será significativo, que le impide hacerlo muy a menudo. La sobrecarga de memoria adicional será relativamente pequeño, ya que será almacenando 2 punteros al mismo objeto, en lugar de 2 copias del mismo objeto. Si las tablas son muy pequeñas, a continuación, se importa mucho menos, de hecho puede ser incluso más rápido para iterar que tener otro mapa de búsqueda.
El enunciado de la pregunta sugiere fuertemente que sin embargo tiene un gran número de artículos a tratar.