Data Realms Fan Forums http://45.55.195.193/ |
|
Table Tutorial http://45.55.195.193/viewtopic.php?f=73&t=45599 |
Page 1 of 1 |
Author: | Bad Boy [ Wed Mar 26, 2014 6:29 pm ] |
Post subject: | Table Tutorial |
A Tutorial On Tables Tables seem to be a confusing thing for a lot of people to grasp, I struggled with it for ages and I think most people trying to learn lua do too, which means they simply avoid them and thus lose the use of an incredibly versatile tool in lua coding. So the purpose of this tutorial is to give a thorough understanding of tables, from start to finish. Thanks for reading. Contents: 1. Intro to tables 2. Array tables and their uses 3. Accessing array table values 4. Dictionary and hash tables and their uses 5. Accessing dictionary/hash tables, the pairs for loop 6. Sorting tables 7. Advanced table uses 1. Intro to tables Tables in Lua are very flexible and versatile, there are a lot of possible ways to use them and I'm sure I'll cover only a fraction of them here. However, the ultimate purpose of any such use is to easily and conveniently store and access information, particularly when compared to using simple variables for everything. Tables are created in lua like any other variable, except that the value is an open curly bracket and a closed curly bracket, as follows: Code: mytable = {} --This creates an empty table You can also create multidimensional tables, i.e. tables with tables inside (it's less complex than it may sound) similarly: Code: mytable = {{}} --This creates an empty 2-dimensional table, i.e. one with another table inside mytable2 = {{{{{{{{}}}}}}}} --This creates an empty 8-dimensional table, i.e. one with 8 layers of tables inside, you should probably never be in a situation where you have to use something like this That covers making a table, but tables are useless until you add items to them. There two ways to do this; table.insert and table[value] = item. The latter is generally more useful, though insert has its advantages. Ultimately, table.insert is simpler so it will be covered first. table.insert is a built in lua function for tables, called in much the same way as, say, math functions (e.g. math.random, math.floor) or string functions (e.g. string.find, string.sub). As such, you need to provide it arguments in the following order: Code: mytable = {} --Make our table myitem1 = "abc"; --Make an item to add to the table table.insert(mytable, myitem1) --This adds myitem1, namely the string "abc" to the end of the table. There is an optional argument to specify the position in the table you want to add it to. myitem2 = "def"; --Make a new item to add to the table table.insert(mytable, 1, myitem2) --This adds myitem2 to position 1 of the table. Thus it is placed before myitem1 in the table and myitem 1 is shifted to position 2of the table --The table's values would now be: "def", "abc" The advantage of using table.insert can be seen when adding myitem2 to the table, it shifts any other items in the table over to make space for the newly added item instead of overwriting items or requiring you to shift everything yourself, the other method does not do this. The more versatile method of adding items to a table is to use table[key] = item. This does pretty much the same thing as the previous method but it won't shift items. It is, however, shorter to type and allows for some very useful tables, which I'll get into later. Similarly, you can add all the table's items when making it, by putting them inside the original curly brackets: Code: mytable = {"abc", "def", "ghi", {"jkl", "mno"}, "pqr"}; --As shown, your table doesn't have to only contain one type of value, you can have strings, numbers, other tables or even functions inside tables. 2. Array tables and their uses The most straightforward way of using a lua table is to use it as an array, which is done by using integer numbers (i.e. 1,2,3,20,etc.) as keys when inserting values. You can insert your values in any order and you don't have to use consecutive numbers, though having a bunch of empty space in a table can slow down its use in some cases. Remember that lua tables start at index 1, so trying to insert something with 0 as the key will not work. Other than that, insertion is exactly like mentioned above: Code: mytable = {} --Make our table mytable[1] = "value 1"; mytable[2] = "value 2"; mytable[20] = "value 20"; --The table's values would be "value 1", "value 2", nil, nil,..., nil, "value 20", where ... is 14 consecutive nil values. --Note that you could also do all of this in one line, though that's inadvisable for large tables mytable2 = {"value 1", "value 2", [20] = "value 20"}; --As you can see, when your value is added in order, you can just write it in, but if you want to skip numbers you have to specify which number to use for the value, in this case 20 Adding values one by one like this is pretty useless, since you could just as easily save them as variables and use those. Fortunately, you can use a loop to add values to a table, saving space and effort: Code: mytable = {} --Make our table for i = 1, 20 do --Repeat 20 times, i will be used as the key for entering table values. It starts at one and each time the loop is finished, it goes up by one until it reaches 20. mytable[i] = "value "..tostring(i); --Set the table's value for i as "value [value of i]" using string concatenation end --The table's values would be "value 1", "value 2", "value 3",..., "value 20" This makes tables far better than simple variables for large amounts of data. 3. Accessing array table values Accessing values in lua tables is quite straightforward, in fact you've seen it already several times in this tutorial. If you want a specific value, you can access it in pretty much the same way you added it: Code: --Using the values entered in section 2 print(mytable[1]); --PRINT: value 1 print(mytable[20]); --PRINT: value 20 etc. As you may have guessed, you can access tables values with a loop in the same way. Lua does have an additional method for accessing array tables, ipairs (short for iterated pairs): Code: --Using the values entered in section 2 --Simple for loop for i = 1, 20 do print(mytable[i]..", i is "..i); --PRINT: value 1, i is 1; PRINT: value 2, i is 2; etc. end --ipairs loop for i, v in ipairs(mytable) do print(v..", i is "..i); --PRINT: value 1, i is 1; PRINT: value 2, i is 2; etc. end You'll notice that both methods do exactly the same thing, however ipairs lets you access the values and their index very easily. It's also particularly useful when you're accessing tables within tables, since there's less difficulty keeping track of names. However, ipairs is slower that a simple for loop by 1.5 or 2 times. But it's a bit nicer to use so if you're not working with a large table it's perfectly fine. 4. Dictionary and hash tables and their uses Array tables are nice, but they're quite standard. Where lua tables excel (in my opinion at least) is in their use as dictionaries and, more importantly, hash tables. For more on hash tables, look here. Suffice to say they allow you to access individual elements of a table without having to know its numerical position in the table. Believe me when I say this is very, very useful for efficiency. Dictionaries can be thought of as arrays with strings instead of numbers for their key. Lua provides some easy way of writing these in, so you don't have to keep track of quotation marks all the time: Code: --Let's say you want put together a table of fruit and their colours fruittable = {}; --You can add values in either of the following ways, they're both completely equivalent fruittable["apple"] = "red"; fruittable.banana = "yellow"; --This version uses lua's 'syntactic sugar' which lets you use .string instead of ["string"] for convenience --You could also do this all in one line, lua also has an easy way of doing this too fruittable2 = {["apple"] = "red", banana = "yellow"}; --Again the second value has no square brackets and quotations. Both ways are completely equivalent. Dictionaries are nice, but hash tables are where this really shines. In lua they're essentially the same as any other table, except you can use just about anything you want as a key. And the best part is, they're no more difficult to make than any other sort of table: Using CC style examples, let's say you have a number of a specific MOSRotatings on a scene and you want to save their position so you can move them around then put them back later. You can do this manually or with an array table, but the first takes up a lot of space and the second requires a lot of extra loops and work to make it actually correct. However, hash tables would make it really easy: Code: local mostable = {}; for mosrotating in MovableMan.Particles do if p.PresetName == "MyDesiredName" then mostable[mosrotating] = mosrotating.Pos; end end --You can then access them easily and move them back with with no difficulty, this'll be covered more in the next section You're of course not limited to just a string or number of vector as the value, you could easily set the value as another table or a function or anything else, so you can store a lot of information about anything very easily: Code: local mostable = {}; for mosrotating in MovableMan.Particles do if p.PresetName == "MyDesiredName" then mostable[mosrotating] = {mosrotating.Pos, mystring = "A specific string", [12] = 12345, ["tableval] = {"A sub table", "with all sorts of values", Vector(123, 456)}, function() return 1 + 2 end}; end end --This gives you the ability to store and access a large amount of information very easily NOTE: The above method doesn't seem to work very well with actors, I think it's because CC is frequently changing their ID so you won't have the exact same value later when you want to access your information. For actors you should use something constant, like lifetime, sharpness or presetname. 5. Accessing dictionary/hash tables, the pairs for loop Accessing individual values in dictionaries and hash tables is done much like it is for arrays: Code: --Using the tables from section 4 print(fruittable["banana"]); --PRINT: yellow print(fruittable.apple); --PRINT: red --Given a local variable 'mos' which is one of the mosrotatings in your table print(mostable[mos]); --PRINT: Vector(x, y) --In the second case - PRINT: table#aefoc2 (if I remember correctly, the random numbers/letters indicate the memory location of the table, they're irrelevant for our purposes) Accessing multiple values at once is much the same as in array tables, however you can't use a simple for loop, since there are no numbers to go through. Instead you use the pairs method to go through the table: Code: --Using the tables from section 4 for k, v in pairs(fruittable) do print(k.." - "..v); --PRINT: apple - red; PRINT: banana - yellow end for k, v in pairs(mostable) do print (k.." - "..v); --PRINT: MOSRotating, MyDesiredName - Vector(x, y); PRINT: ... end --In the second case for the mostable, you could use access each subtable's values individually or use another for loop to print all the values for k, v in pairs(mostable) do print(v[12]); --PRINT: 12345 print(v["mystring"]); --PRINT: A specific string print(v.tableval); --PRINT: table#asfw123sd print(v.tableval[1]); --PRINT A sub table for k2, v2 in pairs(v) do print(k2.." - "..v2); --PRINT: 1 - Vector(x, y); PRINT: mystring - A specific string; etc. end end Code: --Inserting local mytable = {a = 123, [a] = 456}; --The string "a" has value 123 while the variable a has a value of 456 local mytable2 = {12 = 789, [12] = 012}; --The string "12" has value 789 while the value at index 12 (i.e. the number 12) has a value of 012 --Accessing print(mytable.a.." "..mytable["a"].." "..mytable[a]) --PRINT: 123 123 456 - mytable.a is the same as mytable["a"], but mytable[a] uses the variable a print(mytable.12.." "..mytable["12"].." "..mytable[12]) --PRINT: 789 789 012 - mytable.12 is the same as mytable["12"], but mytable[12] uses the number 12 Also note that the pairs iterator will not necessarily give you your values in the order you added them in. Do not use pairs if you need to access values in your table in the same order you inserted them. 6. Sorting tables I'm mainly adding this because it's easy to overlook, lua tables have a built in sorting method, so you can organize things numerically or alphabetically without having to do it yourself. I assume they use an efficient sorting method so it's probably the best way to sort things in lua. table.sort(mytable) will sort a table using the < operator, so it will automatically work with string and number values. It'll probably give issues with things like Vectors and other CC specific values. Fortunately, you can use table.sort(mytable, sortfunction) where sortfunction is a function which takes in two argumens and returns true if the first argument should come before the second in the sorted array (i.e. function sortfunction(v1, v2) returns true if v1 < v2 and false otherwise). Note that table.sort can only be used with array tables, since you can't sort dictionary/hash tables (there's no order to them so sorting them wouldn't do anything). If you can't think of a use for sorted tables, how about proximity checks? Instead of looking through all actors and checking if the SceneMan:ShortestDistance(start, actor.Pos, false) is less than the previous smallest distance, you could add them all to a table, sort it and pull out the first. It saves a lot of lines (though truth be told it's probably less efficient). Look here for more specific stuff about sorting: http://www.lua.org/pil/19.3.html 7. Advanced table uses This is only the surface of lua tables, there's a whole bunch more you can do with them, which I haven't used enough to feel qualified to write about. If you're new to tables or lua, I would suggest avoiding this stuff, but that's your call entirely. You can do stuff with metatables, including pseudo-OOP. A lot of CC's lua stuff uses metatables, so you can effectively break the entire game (until restart) with 1 or 2 lines of lua code! I'll put a few links for those who want to look into this stuff (google it if you want more): Metatables Lua pseudo-OOP Weak tables, these are more about garbage collection in lua, but it's still interesting More metatables More OOP More weak tables More Information Finally, if you want more table tutorial stuff, check out the official lua ones: http://lua-users.org/wiki/TableLibraryTutorial http://www.lua.org/pil/11.html Needless to say, credit for any information in these and all other links I've posted goes to the people who created them. They helped me a lot with learning how to use tables and I'm sure they'll help other people too. Thanks! Thanks for reading, if I made any mistakes or you think there's anything I need to expand on or clarify please let me know. If you have any questions, please don't hesitate to ask, if I think it's worthwhile I'll put up an FAQ for this too based on questions people ask. |
Author: | Bad Boy [ Mon May 12, 2014 2:45 am ] |
Post subject: | Re: Table Tutorial |
Now on steam with its slightly nicer formatting: http://steamcommunity.com/sharedfiles/f ... =259058273 In case anyone's curious, there haven't been any updates to this other than typo fixes, though there were a painful amount of those. I think it's justified since I wrote most of this around 2 - 5 AM. |
Author: | Sims_Doc [ Mon May 12, 2014 2:47 am ] |
Post subject: | Re: Table Tutorial |
Bad Boy wrote: Now on steam with its slightly nicer formatting: http://steamcommunity.com/sharedfiles/f ... =259058273 In case anyone's curious, there haven't been any updates to this other than a few typo fixes. at lest someone is paying attention to guides section, good job! |
Page 1 of 1 | All times are UTC [ DST ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |