warframe tutorial ropa nombre luna for cantante lua

lua - tutorial - ¿Cómo puedo saber si una tabla es una matriz?



lua tutorial (6)

Gracias. Desarrollé el siguiente código y funciona:

---Checks if a table is used as an array. That is: the keys start with one and are sequential numbers -- @param t table -- @return nil,error string if t is not a table -- @return true/false if t is an array/isn''t an array -- NOTE: it returns true for an empty table function isArray(t) if type(t)~="table" then return nil,"Argument is not a table! It is: "..type(t) end --check if all the table keys are numerical and count their number local count=0 for k,v in pairs(t) do if type(k)~="number" then return false else count=count+1 end end --all keys are numerical. now let''s see if they are sequential and start with 1 for i=1,count do --Hint: the VALUE might be "nil", in that case "not t[i]" isn''t enough, that''s why we check the type if not t[i] and type(t[i])~="nil" then return false end end return true end

Estoy desarrollando una función JSON optimizada simple. Lua usa tablas para representar matrices pero en JSON necesito reconocerlas. El código a continuación se usa:

t={ a="hi", b=100 } function table2json(t,formatted) if type(t)~="table" then return nil,"Parameter is not a table. It is: "..type(t) end local ret=""--return value local lvl=0 --indentation level local INDENT=" " --OPTION: the characters put in front of every line for indentation function addToRet(str) if formatted then ret=ret..string.rep(INDENT,lvl)..str.."/n" else ret=ret..str end end addToRet("{") lvl=1 for k,v in pairs(t) do local typeof=type(v) if typeof=="string" then addToRet(k..":/""..v.."/"") elseif typeof=="number" then addToRet(k..":"..v) end end lvl=0 addToRet("}") return ret end print(table2json(t,true))

Como puede ver en la referencia JSON, un object es lo que se llama una table en Lua y es diferente de una array .

La pregunta es ¿cómo puedo detectar si una tabla está siendo utilizada como una matriz?

  • Una solución, por supuesto, es pasar por todos los pares y ver si solo tienen claves numéricas consecutivas, pero eso no es lo suficientemente rápido.
  • Otra solución es poner una bandera en la tabla que dice que es una matriz, no un objeto.

¿Alguna solución más simple / más inteligente?


No, no hay una forma incorporada de diferenciar, porque en Lua no hay diferencia.

Ya existen bibliotecas JSON, que probablemente ya lo hagan (por ejemplo, Lua CJSON .

Otras opciones son

  • Deje que el usuario especifique de qué tipo es el argumento, o de qué tipo le gustaría que lo tratara.
  • tener matrices explícitamente declaradas organizando __newindex manera que solo se __newindex el __newindex nuevos índices numéricos y subsiguientes.

Si desea una solución rápida, simple y no intrusiva que funcione la mayoría de las veces, entonces le diría que simplemente consulte el índice 1; si existe, la tabla es una matriz. Claro, no hay garantía, pero en mi experiencia, las tablas rara vez tienen tanto claves numéricas como otras. Si es aceptable que confundas algunos objetos con matrices y si esperas que esto suceda a menudo depende de tu escenario de uso, supongo que no es bueno para la biblioteca general de JSON.

Editar: Para la ciencia, fui a ver cómo Lua CJSON hace las cosas. Pasa por todos los pares y comprueba si todas las claves son números enteros mientras mantiene la clave máxima (la función relevante es lua_array_length ). Luego decide si serializar la tabla como una matriz u objeto dependiendo de cuán dispersa es la tabla (la relación es controlada por el usuario), es decir, una tabla con índices 1,2,5,10 probablemente se serializará como una matriz, mientras que una tabla con los índices 1,2,1000000 irán como un objeto. Supongo que esta es realmente una buena solución.


@AlexStack

if not t[i] and type(t[i])~="nil" then return false end

Este código es incorrecto, si falla cuando uno de los elementos es false .

> return isArray({"one", "two"}) true > return isArray({false, true}) false

Creo que la expresión completa se puede cambiar a type(t[i]) == nil pero aún fallará en algunos escenarios porque no admitirá valores nulos.

Creo que una buena forma de hacerlo es probar con ipairs o verificar si #t es igual a count , pero #t devuelve 0 con objetos y el count será cero con matrices vacías, por lo que puede necesitar una verificación adicional al comienzo de la función, algo así como: if not next(t) then return true .

Como nota al margen, estoy pegando otra implementación, encontrada en lua-cjson (por Mark Pulford):

-- Determine with a Lua table can be treated as an array. -- Explicitly returns "not an array" for very sparse arrays. -- Returns: -- -1 Not an array -- 0 Empty table -- >0 Highest index in the array local function is_array(table) local max = 0 local count = 0 for k, v in pairs(table) do if type(k) == "number" then if k > max then max = k end count = count + 1 else return -1 end end if max > count * 2 then return -1 end return max end


Escribí esta función para imprimir lindas tablas lua, y tuve que resolver el mismo problema. Ninguna de las soluciones aquí explica los casos extremos, como que algunas teclas son números pero otras no. Esto prueba cada índice para ver si es compatible con ser una matriz.

function pp(thing) if type(thing) == "table" then local strTable = {} local iTable = {} local iterable = true for k, v in pairs(thing) do --if the key is a string, we don''t need to do "[key]" local key = (((not (type(k) == "string")) and "["..pp(k).."]") or k) --this tests if the index is compatible with being an array if (not (type(k) == "number")) or (k > #thing) or(k < 1) or not (math.floor(k) == k) then iterable = false end local val = pp(v) if iterable then iTable[k] = val end table.insert(strTable, (key.."="..val)) end if iterable then strTable = iTable end return string.format("{%s}", table.concat(strTable,",")) elseif type(thing) == "string" then return ''"''..thing..''"'' else return tostring(thing) end end


El algoritmo más simple para diferenciar entre matrices / no matrices es este:

local function is_array(t) local i = 0 for _ in pairs(t) do i = i + 1 if t[i] == nil then return false end end return true end

Explicación aquí: https://web.archive.org/web/20140227143701/http://ericjmritz.name/2014/02/26/lua-is_array/

Dicho esto, todavía tendrá problemas con las tablas vacías, ¿son "matrices" o "hashes"?

Para el caso particular de la serialización de json, lo que hago es marcar matrices con un campo en su metatabla.

-- use this when deserializing local function mark_as_array(t) setmetatable(t, {__isarray = true}) end -- use this when serializing local function is_array(t) local mt = getmetatable(t) return mt.__isarray end