Welcome to the PtokaX Wiki!
This wiki is devoted to let users share information on the great hubsoft PtokaX. However, it is not limited to PtokaX, it is destined to share and discuss information on different parts of the LUA programming language, but the site is NOT intended to be a replacement for the primary LUA Board aka the PtokaX Portal, nor the secondary LUA Board or the PtokaX resources.
If you’re not familiar with wikis then in short: they are user-contributed sites: pages can be edited by (almost) anyone. As such, there is always kind of up-to-date and (hopefully) proper content. They are better than forums, since relevant pieces of information are on the same page. Do not hesitate to share your knowledge, and we all hope you can learn and teach a lot here! — bastya_elvtars
Trace: » Tables & Arrays
This will explain the use of tables in Lua.
To start off, let's see the HOWTO of lua master plop.
Tables & Arrays
Introduction to Tables and Arrays in Lua by plop
Like all the other How-To's were again gone need the lua command line for the examples.
In C/C++ there are tables and array's, in lua the array's are also tables.
array = { "string1", "string2", "string3", "string4", "string5" } tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" }
The table shown here is called an associative table, as the thing before the = is associated with the part after it. Now, most people, would expect that I'm going to start by explaining the arrays first, I'm not going to do that. Because, array's are tables to it's easier initially, to explain the tables. You'll then see easier the link between those two. The table I have made uses numbers as indexes (keys) and strings as values.
Chapter 1: Tables
We're going to start really easy by just printing out all the value's in the table. I used numbers as key's we can retrieve them with this:
tbl[number].
Let's do a simple loop.
print("example 1") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } for index = 1,5 do -- do a loop of 5 steps. print(tbl[index]) end
Now this worked fine but you can allready see a problem, what if there would be more key's in the table?? Indeed, those wouldn't be printed. So, we need a different kind of loop.
print("example 2") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } for key,value in tbl do -- do a loop for aslong as there are key's with value's in the table. print(tbl[key]) end
This method opens up another way. Now, we can also grab the key from the table, which can be handy to have, sometimes. The loop states that there is a key and a value, we can use them directly. Let's print the matching key now along with the value.
print("example 3") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } for key,value in tbl do -- do a loop for aslong as there are key's with value's in the table. print("key= "..key.." and has the value: ".. value) end
Now we know how to process a table. So, let's start with stuffing things into it. Adding things is really simple:
table[6]="string6"
Can't make it more complex than this,… or can I?? Yes, I can. As i'm lazy, we're going to use a loop to extend the table to hold ten keys/values. To show the new table the same loop from the last example is going to be fine for using it also in this.
print("example 4") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } for index=6,10 do -- start a loop from 5 steps starting with index number 6. tbl[index]="string"..index end -- next execute the loop from the last example. for key,value in tbl do -- do a loop for aslong as there are key's with value's in the table. print(tbl[key]) end
Now, let's do the opposite of adding things to the table. We're going to remove keys from 1 to 5. A table can hold everything BUT nil, so all we have to do it declare the keys to be nil.
tbl[1]=nil
We're going to extend the last example with a loop to do this.
print("example 5") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } for index=1,5 do -- start a loop of 5 steps starting with 1. tbl[index]=nil end for index=6,10 do -- start a loop from 5 steps starting with index number 6. tbl[index]="string"..index end -- next execute the loop from the last example. for key,value in tbl do -- do a loop for as long as there are key's with value's in the table. print(tbl[key]) end
Now you might notice that something weird has happened (not on everyone though).
string8 string9 string10 string6 string7
The order is messed up, but no reason to panic at all. This isn't a problem, this is just how lua works. When we remove things we get a free wasted space, this is filled by moving something else to it. But, do remember this, you're going to see the same on array's and there it can cause problems. but before we're going to discuss that we're going to do something that the smartasses have already seen. the first loop removes keys 1 to 5, this is the full table. So, instead of wasting time on the loop we could drop the full table in the garbage bin and declare a new empty table. This, is nearly the same as removing a key,
tbl = nil
drops the table and
tbl = {}
builds a new. Let's do a example again.
print("example 6") tbl = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" } tbl = nil tbl = {} for index=6,10 do -- start a loop from 5 steps starting with index number 6. tbl[index]="string"..index end -- next execute the loop from the last example. for key,value in tbl do -- do a loop for aslong as there are key's with value's in the table. print(tbl[key]) end
now we basicly finished the table part (there are some other way to adress them but not gone discus those here).
Chapter 2: Arrays
Allready told you that array's are tables too, now let me explain how that is posible. for us humans a array looks like this:
array = { "string1", "string2", "string3", "string4", "string5" }
but lua sees it as
array = { [1]="string1", [2]="string2", [3]="string3", [4]="string4", [5]="string5" }
as you can see lua uses indexes for them to, but we never see them in the array. this makes it all a bit spooky, and as a result you might think that it works the same as a associative table but no. array's have there own methods and they can cause big problems if you use them incorrect, the example's are gone show all those things.
Example 6
Let's start with just showing all the value's in the array 1 by 1.
print("example 6") array = { "string1", "string2", "string3", "string4", "string5" } for index=1,5 do print(array[index]) end
now this looks exactly the same as the table version. you can allready start to see that tables and array's are the same in lua. on example to we changed the loop so it would work even if the table held more then 5 things.
Example 7
to make the link between array's and tables totaly clear we're going to use the code from example to again.
print("example 7") array = { "string1", "string2", "string3", "string4", "string5" } for key,value in array do print(array[key]) end
As you can see it works fine. But it's not a nice way of doing it (should be avoided if posible).
Especialy if you think that arrays have a trick up there sleeve which could be used here.
#array gives you the number of value's stored in the array.
Example 8
let's use take the code from example 6 but insert getn.
print("example 8") array = { "string1", "string2", "string3", "string4", "string5" } print("the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
Now we're getting to the hard part, adding removing things to/from the array. You might do it the same way as with tables and it's gone work untill a certain point. The reason for this is that Lua excepts all types of things in a single table.
mixedtable = { "string", [1]="string", ["string"]=2, [15]= function(user, data) dosomething() end, table2={1,2,3} }
As you can see on the above line you mix all sorts, Lua won't complain at all.
But, table.getn works correctly only on a true array. So, think carefully about it before
you try to do such a thing.
Now,… because of this Lua has some special commands to insert and remove
things from an array, table.insert and table.remove. Let's look at table.insert to start with.
table.insert(array,position,value)
The position is something new for us and is optional, if you leave it away it's going to insert the values at the end of the array. If you use it it's going to place it on the matching position. More, on this, later on.
Example 9
Let's take a look at an example based on the previous example 8, again we're going to insert 5 strings.
print("example 9") array = { "string1", "string2", "string3", "string4", "string5" } print("the array has "..table.getn(array).." value's stored in it") for index=6,10 do table.insert(array, "string"..index) end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
As you can see, the strings are added to the array and are in the right order.
The table.getn is automaticly updated to the new amount of value's stored in
the array (the value that table.getn returns is actualy stored in the array in the
last not used space). Now let's try to remove the first five strings by using
the same kind of loop we used for removing things from the table in example 5.
Example 10
print("example 10") array = { "string1", "string2", "string3", "string4", "string5", "string6", "string7", "string8", "string9", "string10" } print("the array has "..table.getn(array).." value's stored in it") for index=1,5 do table.remove(array, index) end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
Now it's about time to panic, has Lua lost it's mind ???
the array has 10 value's stored in it now the array has 5 value's stored in it string2 string4 string6 string8 string10
What was removed were not the first 5 but every odd number, whats going on here?? The answer is simple. The string1 has index 1, but when we remove that string2 gets the index 1.
Example 11
After every insert/remove the key's are updated. To solve this we can do a couple tricks. Let's start simple by just keeping removing index number 1, for five times.
print("example 11") array = { "string1", "string2", "string3", "string4", "string5", "string6", "string7", "string8", "string9", "string10" } print("the array has "..table.getn(array).." value's stored in it") for index=1,5 do table.remove(array, 1) end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
Now this works fine, but what if we just want to remove the indexes 3, 5, 7 and 9. We can't use a loop here and we can't just remove them in the given order??
Example 12
The trick is to work backwards, if we first remove index 9 then 10 becomes 9 but 7 stays 7. Let's take a look at it.
print("example 12") array = { "string1", "string2", "string3", "string4", "string5", "string6", "string7", "string8", "string9", "string10" } print("the array has "..table.getn(array).." value's stored in it") table.remove(array, 9) table.remove(array, 7) table.remove(array, 5) table.remove(array, 3) print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
That worked. Now let's take a step back to example 10. Why ?? Because it could have worked if we would have done what we just learned.
Example 13
If we run the loop backwards it's going to work perfectly.
print("example 13") array = { "string1", "string2", "string3", "string4", "string5", "string6", "string7", "string8", "string9", "string10" } print("the array has "..table.getn(array).." value's stored in it") for index=5,1, -1 do -- start a loop begining with 5 and counting backwars to 1, the -1 tells the loop to count backwards table.remove(array, index) end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
As you can see, the result is now just what we wanted, the first 5 values are gone.
Example 14
Now, let's take a closer look at ”“table.insert”” again but now with position number. Going to get a bit harder now as we're going to fix the broken array from example 10, and by abusing the re-indexing, we're going to use the same backward loop. Let's see what happens….
print("example 14") array = { "string2", "string4", "string6", "string8", "string10" } print("the array has "..table.getn(array).." value's stored in it") for index=5,1, -1 do -- start a loop begining with 5 and counting backwars to 1, the -1 tells the loop to count backwards table.insert(array, index, "string"..index) end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
Nearly correct, they are on the right place just the strings are wrong. Logical as we used the index from the loop.
Example 15
Let's fix this to end this How-To.
print("example 15") array = { "string2", "string4", "string6", "string8", "string10" } print("the array has "..table.getn(array).." value's stored in it") number = 9 -- declaring number to be 9 as it's the first string number we're going to need for index=5,1, -1 do -- start a loop begining with 5 and counting backwars to 1, the -1 tells the loop to count backwards table.insert(array, index, "string"..number) number = number - 2 -- subtracting number by 2 as we need to skip all even numbers end print("now the array has "..table.getn(array).." value's stored in it") for index=1,table.getn(array) do -- start a loop starting with 1 and ending with the highest key stored in the array print(array[index]) end
Now the array is fixed, in a nice orderly way, as it was on the start of example 10.
I hope you enjoyed it and learned to master tables and array's. Happy Scripting.
plop
More On Tables and Arrays
This HOWTO shows a bit more advanced usage of tables/arrays. — bastya_elvtars
Tables and data-storage
Tables/arrays are most commonly used to store data. We might want to retrieve the data sometimes.
Let's assume that we have a table where keys are some cool guys, and values are their wives (not essentially meaning valuable wives though).
wives= { ["Joe"]="Tina", ["Ben"]="Natalie", ["Henry"]="Liz" }
Now let's get who's the wife of Joe.
girl=wives["Joe"]
girl will be “Tina”.
OK, we have a friend , named Tim, who married Shirley. Regardless of the (dis)advantages of the procedure, we have to include them in this table, cause we are pedant.
wives["Tim"]="Shirley"
While we were bothering with this issue, Ben and Natalie divorced. Let's just remove the relevant entry!
wives["Ben"]=nil
Well, so far it seems pretty simple. The table now looks like:
wives= { ["Joe"]="Tina", ["Tim"]="Shirley", ["Henry"]="Liz" }
Now comes the hard part: Joe marries Natalie too, and has 2 wives. This is a crime, the punishment is having 2 mothers-in-law. Nevertheless, we should still be up-to-date. What should we do? Well, tables can also contain arrays (as well as any value). Let's just see how we can include this miserable Joe:
wives["Joe"]={"Tina","Natalie"}
But Natalie is not a devoted one, so she divorces again. Handling this issue now invokes array-specific functions:
table.remove(wives["Joe"],2)
… and Natalie is history.
OK, this was a joke, everything is fine, the 2-on-1 works, but how do we know, whose wife is Natalie? Well, then we introduce a table structure like this:
wives= { ["Joe"]= { ["Tina"]=1, ["Natalie"]=1, } ["Tim"]= { ["Shirley"]=1, } ["Henry"]= { ["Liz"]=1, } }
Note that every guy has a table associated with his name from now on, just in case they wanna follow Joe's example. OK, then comes some innocent guy, asking: “Whose wife is Natalie?” And you have to answer him. Let's see how you can satisfy him:
for a,b in pairs(wives) do if a["Natalie"] then answer=a end end print(answer or "She is single.") -- if no answer, then she is single.
And the guy gets an answer.
Tables can be addressed in a different way:
tbl= { item1=1, item2="sumthin", }
Here we refer to items as table.item1, table.item2 etc. You can, however, refer to them as table[“item1”] too.
If addressing tables this way, you should always have proper variable names nested, otherwise you will get an error.
Now, play with this addressbook sample, try getting values from it, try to find the best way. It's up to you.
addressbook= { ["John Smith"]= { Date_Of_Birth="1977. 07. 28.", Phone= { "+1122334455", "+1122334466", }, Address="7 Mary St., Nowhere", Zip=0000, Occupation="Soup-brewer", }, ["James Wilson"]= { Date_Of_Birth="1966. 01. 15.", Phone= { "+1122334477", "+1122334488", }, Address="7 Lincoln St., Citytown", Zip=2222, Occupation="Ice-welder", } }
Array tricks
LUA has some tricks on arrays that are good to know, because they make your life easier.
table.concat
First one is the table.concat function, which I am sure you will like. It concatenates (merges) thean array, like:
arr={"I ","am ","playing ","with ","arrays."} print(table.concat(arr))
The array can only contain string and numeric values,otherwise you get this:
bad argument #1 to `concat' (table contains non-strings)
You saw that most words have a trailing space. Is it really necessary? No, it isn't. table.concat gets a second argument, which is the separator for concatenation. Let's just change the above code a bit by removing the items' trailing spaces, and give space as sepatrator for table.concat:
arr={"I","am","playing","with","arrays."}
print(table.concat(arr," "))
See? I told you that you would like it.
unpack
This is another handy tool, cause it returns the array elements. It is good to have, cause it's handy when feeding a function with arguments whose number varies even inside the calling function.
function Sum(a,b,c) if b then if c then return a+b+c else return a+b end else return("How could I summarize a single number?") end end function GetNums() print("Please give me numbers.") local args while not args do args=io.read() end local arr={} for w in string.gfind(args,"(%d+)") do table.insert(arr,w) end print(Sum(unpack(arr))) end GetNums()
Another great use is in math.max or math.min.
This will prompt for numbers, enter them separated by non-number characters.
This example is sloppy. If somebody can make a better one, feel free.
Discussion
Please discuss all the above here. It will probably help others, and keeps the community organized.
Checking values in a table
Anyway to do this without having a static interger variable. ? E.g. something like this to remove wife Natalie from Joe.
for a table.getn(wives) do if string.find("Joe", wives) then for b in pairs(wives) do if b["Natalie"] then table.remove(wives[a],[b]) end end end end
Or won't this work / or have i gone a really bad way about doing this ?
for i,v in wives["Joe"] do if v == "Natalie" then table.remove(wives["Joe"],i) end end
and pass the doobie, bogart![]()
for i,v in pairs(wives["Joe"]) do if v == "Natalie" then table[i]=nil end end
Without a function call, it is faster. :P — bastya_elvtars
As an alternative way (one not doing a for loop through the whole table), would this work ?
if (wives["Joe"]["Natalie"] ~= nil) then wives["Joe"]["Natalie"] = nil end
If this is good, only the middle line should be needed, for the particular example. The other 2 lines are just as an error prevention check.
if wives["Joe"] and table.getn(wives["Joe"]) > 0 then wives["Joe"]["Natalie"] = nil end
This way we just check if Joe is married at all. — bastya_elvtars
You are here: About the Wiki » scriptinghelp » Tables & Arrays