[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Tables in Lua

Tables in Lua

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Wed 24 Nov 2004 03:05 AM (UTC)

Amended on Sat 07 Apr 2007 06:56 AM (UTC) by Nick Gammon

Message
Tables are a fundamental part of the Lua design. You can make your own very easily, and store anything you like in them (including other tables).

For example, say you want to keep track of some mobs:


mobs = {}  -- create mobs table


The above line creates a table, which you can then put data into, in various ways. Let's make an individual mob another table, and then store relevant parts keyed by name:


mobs.kobold = {
  name = 'killer',
  hp = 22,
  gold = 5,
  location = 'city square'
  }

-- and another one ...

mobs.worm = {
  name = 'gordon',
  hp = 4,
  gold = 15,
  location = 'underground'
  }



Now we can start to look at this data. First, we'll print the mobs table:


print (mobs)  --> table: 00629490


You can type these examples into the MUSHclient command window (prefixed by the scripting prefix "/"), or into the Immediate scripting window.

It is all very well knowing we have a table, but what is in it? A useful feature of Lua is the "table.foreach" instruction which lets you iterate over a table. eg.


table.foreach (mobs, print)

-- output:

worm table: 006303E0
kobold table: 00630560


This is printing (ie. doing a world.Note) each entry in the table. First you see the key, and then the data. The data in this case is another table.

An alternative way of doing this is with a loop:


for k, v in pairs (mobs) do 
  print ("key = ", k, " value = ", v)
end

-- output:

key =  worm  value =  table: 006303E0
key =  kobold  value =  table: 00630560


But what is the value for the kobold? Well, we just repeat the exercise for the sub-table:


table.foreach (mobs.kobold, print)

-- output:

name killer
gold 5
location city square
hp 22


We can also access individual fields by delimiting them with dots, like this:


print (mobs.kobold.hp)  --> 22





Recursive table printer

If you are playing with tables a lot, a recursive printing function might be helpful. Here is an example:


function tprint (t, indent, done)
  done = done or {}
  indent = indent or 0
  for key, value in pairs (t) do
    Tell (string.rep (" ", indent)) -- indent it
    if type (value) == "table" and not done [value] then
      done [value] = true
      Note (tostring (key), ":");
      tprint (value, indent + 2, done)
    else
      Tell (tostring (key), "=")
      print (value)
    end
  end
end


To use this, just call it with a table, eg.


tprint (mobs)

-- output:

worm:
  name=gordon
  gold=15
  location=underground
  hp=4
kobold:
  name=killer
  gold=5
  location=city square
  hp=22


That is neat - now we can see the table, and any sub-tables, in a single command.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Berthiaume   (202 posts)  [Biography] bio
Date Reply #1 on Sat 11 Dec 2004 03:21 PM (UTC)
Message
Where would you place the table? Obviously it wouldn't be in a trigger.... Also how to I create a Lua script file?

I used to have myscript.vbs, but with the new language, not sure how to create one.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Sat 11 Dec 2004 09:38 PM (UTC)
Message
You put the table where you put other global variables. Normally that would be in your script file, so it is in the "global script spaces".

The Lua script file is just a text file. I would call it something like myscript.lua.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Berthiaume   (202 posts)  [Biography] bio
Date Reply #3 on Sun 12 Dec 2004 12:09 AM (UTC)
Message
So make a text file called whatever.lua and load it like I would a whatever.vbs?

Seems simple enough, though you mentioned something about the Lua in the global preferences. Is that the same as loading a .lua script file i nthe scripting options in game>configure>scripting?

If so wouldn't there be a conflict having 2 script files?

Additionally, is loading a script file necessary if you can simply use the global preferance file?
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #4 on Sun 12 Dec 2004 01:44 AM (UTC)
Message
Quote:

So make a text file called whatever.lua and load it like I would a whatever.vbs?


Yes.


Quote:

If so wouldn't there be a conflict having 2 script files?


No, they both execute in the global script space for that world, so effectively you have one set of commands followed by another.

However the global preferences was intended for setting up a secure sandbox, not to have all your scripts in it. For one thing, it is kept in the registry, and if you have thousands of lines of script in it, it will bloat the registry. Also, if you lose the registry (eg, reinstall Windows) then you have lost all your scripts.

If you must do that, put all your scripting into a file, and then in the global preferences, just do:

dofile "path_to_my_script_file.lua"

However I think the preferable thing is to simply have a script file like you do for VB and quote that file's name in the scripting preferences.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by MaXXmaster   (1 post)  [Biography] bio
Date Reply #5 on Sun 30 Oct 2005 07:53 AM (UTC)

Amended on Sun 30 Oct 2005 09:22 PM (UTC) by Nick Gammon

Message
Hi! I've been looking for a function that has exactly the same functionality as the php function print_r (recursive printing of anything, tables, values, what ever...)

so i stumbled across your posting, with minor changes in your source, i managed to make quite a good clone of php's print_r which works fine in lua5 as well.

source:


function print_r (t, indent, done)
    done = done or {}
    indent = indent or 0
    if type(t) == "table" then
        for key, value in pairs (t) do
            io.write(string.rep (" ", indent)) -- indent it
            if type (value) == "table" and not done [value] then
              done [value] = true
              io.write(string.format("[%s] => table\n", tostring (key)));
              io.write(string.rep (" ", indent+4)) -- indent it
              io.write("(\n");
              print_r (value, indent + 7, done)
              io.write(string.rep (" ", indent+4)) -- indent it
              io.write(")\n");
            else
              io.write(string.format("[%s] => %s\n", tostring (key),value))
            end
        end
    else
        io.write(t .. "\n")
    end
end



maybe this helps any other php programmer that wants to use lua for some reason.

cheers
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Sun 30 Oct 2005 09:23 PM (UTC)
Message
Thanks, I amended your post to put in the [code] tag to show formatting better.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #7 on Mon 31 Oct 2005 04:25 AM (UTC)
Message
For more information about Lua tables, see Lua tables in detail.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Siluri   (5 posts)  [Biography] bio
Date Reply #8 on Tue 28 Mar 2006 03:39 PM (UTC)
Message
Just starting out with LUA, I found the 2 dimension table sort topic *very* useful after searching everywhere for that info.

so a question on tables if I may...

I have a master table of players and i want to copy a sub-set of this into another table based upon a filter.

EG

mastertable[1] = {["id"]=1, ["name"]="fred", ["class"]="a"}
mastertable[2] = {["id"]=1, ["name"]="bill", ["class"]="b"}
mastertable[3] = {["id"]=1, ["name"]="john", ["class"]="a"}
mastertable[4] = {["id"]=2, ["name"]="frank", ["class"]="b"}
mastertable[5] = {["id"]=2, ["name"]="robert", ["class"]="a"}

So so way of doing a table.foreach on the mastertable, checking if the "id" == a value and then any matching records copied to a new table. If I was after "id"=2 then

copytable[1] = {["id"]=2, ["name"]="frank", ["class"]="b"}
copytable[2] = {["id"]=2, ["name"]="robert", ["class"]="a"}

The following code doesn't work although I think it's not a million miles away...

table.foreach (mastertable, function() table.insert (copytable,
function (k, v)
if v.number == id then
return k
end -- if
end -- function
end -- function
)
)

Thanks in advance.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Tue 28 Mar 2006 08:08 PM (UTC)

Amended on Tue 28 Mar 2006 08:09 PM (UTC) by Nick Gammon

Message
I believe table.foreach is being deprecated in Lua 5.1, so you could do it in a simple loop:


copytable = {}

for k, v in ipairs (mastertable) do
  if v.id == 2 then
    table.insert (copytable, v)
  end -- if
end -- for


That works OK, and is easy to read.

However you can certainly do it with table.foreach. I don't know why you had 2 functions, one is enough. Also I would use table.foreachi since your table seems to be numerically indexed:


copytable = {}

table.foreachi (mastertable, 
  function (k, v)  -- key, value
    if v.id == 2 then
      table.insert (copytable, v)
    end -- if
  end -- function
  )  -- end foreachi


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Tue 28 Mar 2006 08:15 PM (UTC)

Amended on Tue 28 Mar 2006 08:41 PM (UTC) by Nick Gammon

Message
Of course, you can make a more generic "table copy" function, like this:



-- generic table filter function

function filtertable (t, f)
  assert (type (t) == "table")
  assert (type (f) == "function")
  local k, v
  local result = {}
  for k, v in ipairs (t) do
    if f (v) then
      table.insert (result, v)
    end -- if
  end -- for
  return result
end -- filtertable 


-- example

copytable = filtertable (mastertable, 
                         function (v) return v.id == 2 end 
                        )


What this does is make a function that makes a copy of the supplied table, where you simply supply a function that returns true if you want the table item to be included, and false if not.

I threw in a couple of asserts to check that the arguments are what you expect.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Siluri   (5 posts)  [Biography] bio
Date Reply #11 on Tue 28 Mar 2006 09:52 PM (UTC)
Message
fantastic!

I knew the code should be short and elegant but i had the blinkers on i suspect.

Also thanks for the warning on LUA 5.1, i will follow your advice.

:-)
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Tue 28 Mar 2006 10:05 PM (UTC)
Message
Also you can simplify your table definition, assuming what you did was not just an example. Instead of:


mastertable[1] = {["id"]=1, ["name"]="fred", ["class"]="a"}
mastertable[2] = {["id"]=1, ["name"]="bill", ["class"]="b"}


You can use:


mastertable[1] = {id=1, name="fred", class="a"}
mastertable[2] = {id=1, name="bill", class="b"}

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Siluri   (5 posts)  [Biography] bio
Date Reply #13 on Tue 28 Mar 2006 10:06 PM (UTC)
Message
a follow up question!

what's the best way of emptying a table since they can't be deleted?

1. just a table.setn = 0? so the contents get's overwritten
2. do a table.remove in a foreach?
3. do a loop setting each element to null?

Thanks
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Tue 28 Mar 2006 10:38 PM (UTC)

Amended on Wed 29 Nov 2006 09:29 PM (UTC) by Nick Gammon

Message

mastertable = nil


That will remove the reference to the table, and the garbage collector will collect it. Or, if you want to empty it, and keep it as a table:


mastertable = {}  -- make new, empty, table


If, for some reason, you need to keep the table the same (for example, you have references to it elsewhere), you can do this:


for k in pairs (mastertable) do
  mastertable [k] = nil
end -- for

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


96,449 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]