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?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top