i know i can construct tables like this:
local t= {
first = "value1",
second = "value2"
}
and i now i can use keys containing spaces like t["some key"] = "some value"
but is there a way to construct table like above with keys containing spaces?
I tried a few things, but i only goit errors
You can declare any expression as a key in a table constructor by putting it in brackets:
local t = {
["some key"] = "some value",
[234567 + 2] = "other value",
}
local t= {
first = "value1",
second = "value2"
}
Is syntactic sugar for
local t= {
["first"] = "value1",
["second"] = "value2"
}
This convenient syntax only works for names. Lua names may only consist of letters, numbers and underscore and they must not start with a number.
As a valid Lua identifer may not contain a space you cannot use the syntactic sugar. Hence the only way to do this is to use the full syntax
local t = {["hello world"] = 1}
This also applies to indexing that table field. So the only way is t["hello world"]
Related
I recently wrote some code like this:
function enum(tbl)
local length = #tbl
for i = 1, length do
local v = tbl[i]
tbl[v] = i
end
return tbl
end
eItemType = enum
{
"wpn",
"outf",
"helm",
"art",
"boost",
"bkpk",
"dev",
"ammo",
"none"
}
It works. But I would like to simplify it to this form:
enum eItemType
{
"wpn",
"outf",
"helm",
"art",
"boost",
"bkpk",
"dev",
"ammo",
"none"
}
For the enum function to create a global variable eItemType in the file from which it is called.
I don't know how to implement this (convert eItemType to string in string code).
Functions from the debug library come to mind, namely getline, maybe it can handle it...
Enumerations in Lua
First of all: You're shoehorning a foreign language concept into Lua, which will necessarily not be round on the corners. Languages like C use numbers (integers) for enums because of their efficiency: Integer comparison is fast. In the end, enums are just synctactic sugar for enumerating integer constants though. You don't need any of this in Lua: Lua has string interning, which means strings are only stored once in memory and can be compared as fast as numbers. That is, the naive way to implement enums in Lua, is to simply use strings right away!
local enum_values = {"foo", "bar", "baz"}
local function get_random_enum_value()
return enum_values[math.random(#enum_values)]
end
if get_random_enum_value() == "foo" then
print("Congratulations! The value is foo!")
end
The downside is that you now don't have any table holding your enum values, so you'll either want to brush up on your documentation or create a (redundant) hash table to hold your enum values (which really is just making things slower, but may help readability). You don't need to involve any numbers. If I inspect a table and see a "foo_something" string there, that's a lot more useful than 42.
local my_enum = {foo = "foo", bar = "bar", baz = "baz"}
local enum_values = {my_enum.foo, my_enum.bar, my_enum.baz}
local function get_random_enum_value()
return enum_values[math.random(#enum_values)]
end
-- May be considered more readable since we now have a scope for "foo"
if get_random_enum_value() == my_enum.foo then
print("Congratulations! The value is foo!")
end
then you'd probably write yourself a simple helper to generate these kinds of tables:
function enum(namelist)
local t = {}
for _, v in pairs(namelist) do
t[v] = v
end
return t
end
my_enum = enum{
"foo",
"bar",
"baz",
}
Syntactic Sugar
What you want is called syntactic sugar and yes, it requires Lua's metaprogramming capabilities. If you really want an enum keyword, you'll have to extend Lua or implement a preprocessor adding such a keyword.
First, let's see how Lua sees your current code:
someName = enum { ... }
parses as "call the variable called enum with the table { ... } and assign the result to the variable called someName".
enum someName { ... }
does not parse: this is just a name, followed by... another name? Syntax error. By slightly abridging this syntax, it is however still possible to turn this into a valid expression. How about passing someName as a string to enum, which then returns a function to apply to your table?
enum "someName" { ... }
this would be implemented as
function enum(name)
return function(t)
_G[name] = original_enum(t)
end
end
where original_enum is your original enum function without the added layer for syntactic sugar. You might want to swap out _G with _ENV or getfenv(2) or similar.
Or for another syntactic sugar, you could also use the indexing operator paired with the __index metamethod:
enum.someName { ... }
which is implemented as:
enum = setmetatable({} --[[proxy table]], {__index = function(_, name)
return function(t)
_G[name] = original_enum(t)
end
})
both of these have in common that they are basically just fancy ways of currying the name of the global variable you want to assign to.
f you need to get a table from a string, then try:
local s = [[ return {
"wpn",
"outf",
"helm",
"art",
"boost",
"bkpk",
"dev",
"ammo",
"none"
}]]
eItemType = (loadstring or load)(s)() -- since Lua 5.2 loadstring has been replaced by load
for k,v in pairs(eItemType) do
print( k,v)
end
if you need a full copy of a simple table , then it is created like this:
enum = function(t)
local tmp = {}
for _,v in ipairs(t) do tmp[#tmp+1]=v end
return tmp
end
eItemType = enum {
"wpn",
"outf",
"helm",
"art",
"boost",
"bkpk",
"dev",
"ammo",
"none"
}
if you need to move the creation of a global table or enumerations to another place, look at the solution through modules
and the last solution is to get a line of code from a simple table, used to write to a file and generate lua code
function dumpValue(obj)
local s = '\n{ '
for k,v in ipairs(obj) do
s = s .. '\n['..k..'] = "' .. v .. '",'
end
return s .. '} '
end
print(dumpValue(eItemType))
In the command
table.insert(table, data)
how can you use that but for the inserts have string keys?
PSEUDO CODE
tableOfStuff = {cat, pig, hat, lemon}
t = {}
for i=1, #tableOfStuff do
table.insert(t, key=tableOfStuff[i], data=tableOfStuff[i])
end
So I end up with a table...
t['cat'] == 'cat'
t['dog'] == 'dog'
etc.....
EDIT
I think my example confused people... I am asking how to use "insert.table" but insert tings with string keys...
table.insert(table,data,stringkey)
something like this?
Creating One Table
If all you want is to create a table with strings as keys, then check out Table Constructors, you have a couple options.
Option 1:
t = { key1 = "value1", key2 = "value2" }
--or like this:
t = { ["key1"] = "value1", ["key2"] = "value2" }
Option 2: (create an empty table first)
t = {}
t.key1 = "value1"
--or like this
t["key2"] = "value2"
It looks like you want the keys and values to be the same string and that is possible. Just write the same thing for key1 and value1. So t["cat"] = "cat".
Using Two Tables
Based on your example code, it looks like you want to take an existing table of strings and create from that a new table with strings as both the keys and the values. To do that:
table1 = { "cat", "pig", "hat", "lemon" }
table2 = {}
for i=1, #table1 do
table2[ table1[i] ] = table1[i]
end
--test
print table2["cat"]
Here is a good lesson about tables in Lua: Lua Tables Tutorial
The comment is right.You needn't and you can't use table.insert.You can see the document table.insert.It's only support the number.It' used for the array part of table.But you're using the hash part of a table.
code:
tableOfStuff = {"cat", "pig", "hat", "lemon"}
t = {}
for i=1, #tableOfStuff do
local szKey = tableOfStuff[i];
t[szKey] = tableOfStuff[i]; -- the value can be the others.
end
I realize this is usually not a great practice, but how would I use a string containing an integer (e.g. "7") as a table key? For example:
local myTable = {
"1" = "Foo",
"2" = "Bar"
}
If memory serves from reading the Lua manual back in the day, that should be possible with some special syntax, but what I've written above is a syntax error.
Like this:
local myTable = {
["1"] = "Foo",
["2"] = "Bar"
}
Because the keys are not valid identifiers, you can't use the syntax sugar form.
Just picking upon Lua and trying to figure out how to construct tables.
I have done a search and found information on table.insert but all the examples I have found seem to assume I only want numeric indices while what I want to do is add key pairs.
So, I wonder if this is valid?
my_table = {}
my_table.insert(key = "Table Key", val = "Table Value")
This would be done in a loop and I need to be able to access the contents later in:
for k, v in pairs(my_table) do
...
end
Thanks
There are essentially two ways to create tables and fill them with data.
First is to create and fill the table at once using a table constructor. This is done like follows:
tab = {
keyone = "first value", -- this will be available as tab.keyone or tab["keyone"]
["keytwo"] = "second value", -- this uses the full syntax
}
When you do not know what values you want there beforehand, you can first create the table using {} and then fill it using the [] operator:
tab = {}
tab["somekey"] = "some value" -- these two lines ...
tab.somekey = "some value" -- ... are equivalent
Note that you can use the second (dot) syntax sugar only if the key is a string respecting the "identifier" rules - i.e. starts with a letter or underscore and contains only letters, numbers and underscore.
P.S.: Of course you can combine the two ways: create a table with the table constructor and then fill the rest using the [] operator:
tab = { type = 'list' }
tab.key1 = 'value one'
tab['key2'] = 'value two'
Appears this should be the answer:
my_table = {}
Key = "Table Key"
-- my_table.Key = "Table Value"
my_table[Key] = "Table Value"
Did the job for me.
Say that you want to create a Lua table, and all its keys are valid lua identifiers. Then you can use the key=value syntax:
local niceTable = { I=1, like=1, this=1, syntax=1 }
If however your strings are not "identifiable", then you have to use the ['key']=value syntax:
local operators = { ['*']="Why", ['+']="the", ['/']="brackets", ['?']='?' }
I'm a bit baffled about this. What are those brackets doing there? What do they mean?
They identify the contained string as a key in the resulting table. The first form, you could consider as equal to
local niceTable = {}
niceTable.I = 1;
niceTable.like = 1;
The second form is equal to
local operators = {}
operators['*'] = "Why";
operators['+'] = "The";
The difference is purely syntactic sugar, except where the first one uses identifiers, so it has to follow the identifier rules, such as doesn't start with a number and interpret-time constant, and the second form uses any old string, so it can be determined at runtime, for example, and a string that's not a legal identifier. However, the result is fundamentally the same. The need for the brackets is easily explained.
local var = 5;
local table = {
var = 5;
};
-- table.var = 5;
Here, var is the identifier, not the variable.
local table = {
[var] = 5;
};
-- table[5] = 5;
Here, var is the variable, not the identifier.
The normal syntax for indexing a table is t[val]. For string keys only, Lua provides an alternate syntax, where t.foo is exactly equivalent to t["foo"]. This is purely a syntactical convenience, so-called 'syntax sugar'. It doesn't add functionality, it just gives you a less cluttered syntax for using strings as named fields.
There are a lot of strings keys this won't work for:
t["hello_world"] => t.hello_world -- works
t["hello world"] => t.hello world -- oops, space in the string
t["5 * 3"] => t.5 * 3 -- oops
t['[10]'] => t.[10] -- oops
Basically it only works if the string key would be a valid identifier.
Again, tables are indexed via [], and in most cases you need to use them:
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
["foo"] = 123, -- string key, number value
}
Only if you're using a string key which would work as a valid identifier (no spaces, contains only word characters, numbers, or underlines, and doesn't begin with a number) can you use the shortcut syntax. For the table above, that would be only 'foo':
t = {
-- [key] = value
[10] = "ten", -- number key, string value
["print function"] = print, -- string key, function value
["sub table"] = {}, -- string key, table value
[print] = 111, -- function key, number value
foo = 123, -- string key, number value
}