2010-02-17 30 views
74

¿Hay algún método para verificar si una tabla contiene un valor? Tengo mi propia función (ingenua), pero me preguntaba si existe algo "oficial" para eso. O algo más eficiente ...¿Cómo comprobar si una tabla contiene un elemento en Lua?

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 algo más que pueda usar?

+2

¿Qué significa la _, notación? – Martin

+18

Es simplemente una variable "basura" llamada '_'. 'pairs()' devuelve 'key, value', pero en este ejemplo solo necesito el valor. Es una especie de convención (adoptada en el libro "Programación en Lua" http://www.lua.org/pil/index.html) para usar esta variable '_' para almacenar cosas que no necesita. – Wookai

Respuesta

91

Puede poner los valores como las 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 completo here.

+12

Un usuario anónimo propuso la siguiente solución a su código: si el valor en el conjunto con la clave especificada es FALSE, la función setContains() devuelve un valor falso aunque haya un elemento en la tabla con la clave especificada. la línea "return set [key] ~ = nil" corrige ese error. – oers

2

No puedo pensar en otra forma de comparar valores, pero si usa el elemento del conjunto como la clave, puede establecer el valor en cualquier valor que no sea nada. Luego, obtiene búsquedas rápidas sin tener que buscar en toda la tabla.

22

Dada su representación, su función es tan eficiente como se puede hacer. Por supuesto, según lo observado por otros (y como se practica en idiomas anteriores a Lua), la solución a su problema real es cambiar la representación. Cuando tiene tablas y quiere conjuntos, convierte las tablas en conjuntos utilizando el elemento set como la clave y true como valor. +1 a interjay.

0

Sé que esta es una publicación anterior, pero quería agregar algo para la posteridad. La forma simple de manejar el problema que tiene es hacer otra tabla, de valor para la clave.

es decir. tienes 2 tablas que tienen el mismo valor, una apuntando en una dirección, una apuntando en la otra.

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 iterar a través de cada valor de la otra tabla.

Si resulta que no puede usar el 'elemento' como clave, porque no es una cadena, por ejemplo, agregue una suma de comprobación o 'toString' en ella, por ejemplo, y luego use eso como llave.

¿Por qué quieres hacer esto? Si sus tablas son muy grandes, la cantidad de tiempo para iterar a través de cada elemento será significativa, lo que le impedirá hacerlo con mucha frecuencia. La sobrecarga de memoria adicional será relativamente pequeña, ya que almacenará 2 punteros para el mismo objeto, en lugar de 2 copias del mismo objeto. Si sus tablas son muy pequeñas, importará mucho menos, de hecho puede incluso ser más rápido iterar que tener otra búsqueda en el mapa.

La redacción de la pregunta, sin embargo, sugiere fuertemente que tiene una gran cantidad de elementos para tratar.

+0

Una buena explicación, pero realmente no agrega nada a la discusión. Probablemente hubiera sido una mejor idea editar la respuesta de Interjay. – bcdan

+0

Además, '.key' debe reemplazarse por '[key]' en todas partes en este código (lo mismo con 'value') – Njol

Cuestiones relacionadas