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


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Nested tables

Nested tables

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


Pages: 1 2  

Posted by Metho   (8 posts)  [Biography] bio
Date Thu 11 Feb 2010 09:49 PM (UTC)
Message
I'm looking for some help in wrapping my head around how to properly create this series of nested tables, and how to update them. Here's my situation:

I have 10 stores. When I can do check <storename> I can see their contents - which includes item, buy price, stock, and sell price.

The items in all 10 stores are the same, so I simply want to check each one, and be able to manipulate the data for comparison (i.e. find the store with the lowest priced object, ect.)

So I was thinking one table called stores, nested inside is store1 store2, ect., and nested inside is itemname, buyprice, stock, sellprice.

My problem lies in the actual coding, I guess. I need it to select the table by one trigger, but capture the data to put in it by another. Like so:

*******************The Ledger for the Village of Acknor********************


This would do something like SetVariable("cur_village", "%1") where %1 is acknor.

Then lines after that are like this:
Wood                       8 gp             130           73 gp

So, I want that data to go into stores[acknor][wood][8, 130, 73]

Note: I don't need help with the regex, that's easy. Just failing in the actual scripting part.

I get errors when I try to set the table by variable. Like cur_village{}. It says it's a string, which, fair enough, I'll agree. So I'm not sure how to turn cur_village{} into acknor{} or whatever cur_village is currently.

Guess I've got pieces of the solution in my head, but I'm having trouble solving everything/putting it all together. Any suggestions/ideas are appreciated.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Thu 11 Feb 2010 10:03 PM (UTC)
Message
Without seeing your code it is hard to see exactly where the confusion arises, but something like this is the way to go:


stores = {}   -- make table (first time)

-- create sub-table for acknor, if not already exists
stores ["acknor"] = stores ["acknor"] or {}

-- get reference to save typing
store = stores ["acknor"]

-- store details about wood
store ["wood"] = { buy = 8, stock = 130, sell = 73 }

-- and iron
store ["iron"] = { buy = 15, stock = 5, sell = 85 }


Now if you "table print" it you can see everything nicely:


require "tprint"
tprint (stores)


Output:

"acknor":
  "wood":
    "sell"=73
    "stock"=130
    "buy"=8
  "iron":
    "sell"=85
    "stock"=5
    "buy"=15





- Nick Gammon

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

Posted by Metho   (8 posts)  [Biography] bio
Date Reply #2 on Thu 11 Feb 2010 10:17 PM (UTC)
Message
Ok, that cleared most things up. I don't have Mushclient available in front of me at this second, so excuse me for not testing before asking, but can I just do something like store = stores ["@cur_village"] with expand variables checked instead? I ask because one trigger is used for all stores to capture the data:

-- Regex pattern ^(\w+)\s+(\d+)\sgp\s+(\d+)\s+(\d+)\sgp$

store = stores["@cur_village"]

store["%1"] = { buy = %2. stock = %3, sell = %4 }

That regex pattern is going to fire no matter what store (village) is displaying, so the setting of the store has to be variable in that trigger.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Thu 11 Feb 2010 11:14 PM (UTC)
Message
Yes that should work, provided a previous trigger (not this one) set up curr_village.

- Nick Gammon

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

Posted by Metho   (8 posts)  [Biography] bio
Date Reply #4 on Fri 12 Feb 2010 07:16 PM (UTC)
Message
Thanks for the help, after a few little tweaks, I got it to work. If I could ask one more question. I read the stuff on tables in detail, and I've tried to get this to work, but I seem to be doing it wrong.

I'm trying to select values based on comparisons. So like if I tprint (stores) I get:

"Acknor":
  "Wood":
    "sell"=68
    "stock"=0
    "buy"=8
  "Silver":
    "sell"=118
    "stock"=0
    "buy"=14
"Paavik":
  "Wood":
    "sell"=68
    "stock"=104
    "buy"=5
  "Silver":
    "sell"=119
    "stock"=0
    "buy"=5

This list is abbreviated. There are more items and more stores. But it gives you the pattern. I'm used to MySQL, but I'd basically like to do something like select wood from stores where stock isn't 0 and display the store name. Or select the store where wood is the lowest sell price, ect.

I'm assuming this is some kind of recursive voodoo, but I've been either getting comparing table to number errors or no results (even with trace on), or other "You're not bright" errors.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Fri 12 Feb 2010 09:09 PM (UTC)

Amended on Sat 13 Feb 2010 12:32 AM (UTC) by Nick Gammon

Message
Well, you can import the data into a SQLite3 memory database, but sticking with tables, we can have fun playing with them ...

To analyze by item (rather than by store) we probably need the items at the top level rather than stores, so we can more easily sort and compare.

One approach is to simply store the data differently, eg.


goods = goods or {}

goods ["%1"] = goods ["%1"] or {}

goods ["%1"] ["@cur_village"] = { buy = %2, stock = %3, sell = %4 }


That way the highest table is goods (eg. wood, silver) and the next level down is where you found them.

But assuming you already have your data, you can convert the table easily enough:



-- test data
stores = {
  Acknor = {
    Wood = {
      sell = 68,
      stock = 0,
      buy = 8,
      },
    Silver = {
      sell = 118,
      stock = 0,
      buy = 14,
      },
    },
  Paavik = {
    Wood = {
      sell = 68,
      stock = 104,
      buy = 5,
      },
    Silver = {
      sell = 119,
      stock = 0,
      buy = 5,
      },
    },
  }

-- convert table into one with the goods at the top level

goods = {}
for store, inventory in pairs (stores) do
  for item, details in pairs (inventory) do
    goods [item] = goods [item] or {}  -- make sure this item exists
    goods [item] [store] = details
  end -- for each item
end -- for each store

-- show results
print (string.rep ("-", 60))
tprint (goods)
print (string.rep ("-", 60))

-- get goods in alphabetic order

goods_alpha = {}
for k in pairs (goods) do
  table.insert (goods_alpha, k)
end -- for

table.sort (goods_alpha)

-- show each item

for _, item in ipairs (goods_alpha) do
  print ""
  print (item)
  print (string.rep ("-", 60))
  
  -- stores that stock this item
  local item_store = {}
  for k in pairs (goods [item]) do
    table.insert (item_store, k)
  end -- for
  
  table.sort (item_store, function (a, b)
              return goods [item] [a].buy < goods [item] [b].buy
              end)
  
  for _, store in ipairs (item_store) do
    print (store, 
          "Buy", goods [item] [store].buy,
          "Sell", goods [item] [store].sell,
          "Stock", goods [item] [store].stock)
           
  end -- for
end -- for



Output from the above:


------------------------------------------------------------
"Wood":
  "Acknor":
    "sell"=68
    "stock"=0
    "buy"=8
  "Paavik":
    "sell"=68
    "stock"=104
    "buy"=5
"Silver":
  "Acknor":
    "sell"=118
    "stock"=0
    "buy"=14
  "Paavik":
    "sell"=119
    "stock"=0
    "buy"=5
------------------------------------------------------------

Silver
------------------------------------------------------------
Paavik Buy 5 Sell 119 Stock 0
Acknor Buy 14 Sell 118 Stock 0

Wood
------------------------------------------------------------
Paavik Buy 5 Sell 68 Stock 104
Acknor Buy 8 Sell 68 Stock 0


Once I converted the table into having goods at the top, followed by villages, I made another temporary table (goods_alpha) which let me sort them into alpha order (so silver comes before wood).

Then iterating through that table with ipairs, for each item we then make yet another temporary table for each store that sells that item (item_store).

A sort with a custom compare function then sorts those items into buy order (change the word "buy" in two places to sort into sell or stock order).

Then we print the results.


- Nick Gammon

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

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Fri 12 Feb 2010 09:12 PM (UTC)

Amended on Sat 13 Feb 2010 12:35 AM (UTC) by Nick Gammon

Message
Metho said:

I'd basically like to do something like select wood from stores where stock isn't 0 and display the store name.


Well that is simpler:



-- test data
stores = {
  Acknor = {
    Wood = {
      sell = 68,
      stock = 0,
      buy = 8,
      },
    Silver = {
      sell = 118,
      stock = 0,
      buy = 14,
      },
    },
  Paavik = {
    Wood = {
      sell = 68,
      stock = 104,
      buy = 5,
      },
    Silver = {
      sell = 119,
      stock = 0,
      buy = 5,
      },
    },
  }

for store, inventory in pairs (stores) do
  for item, details in pairs (inventory) do
    
    if item == "Wood" and details.stock > 0 then
      print (store, details.stock, "in stock")
    end -- if
  
  end -- for each item
end -- for each store


Output:


Paavik	104	in stock

- Nick Gammon

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

Posted by Bitttttor   Australia  (6 posts)  [Biography] bio
Date Reply #7 on Wed 17 Feb 2010 11:03 AM (UTC)
Message
Hi, I'm new here... great forum, congrats
I'm following your discussion about nested tables for a project I've just started. The problem is when I try to feed the tables with a for loop:

a = {}
a ["b"] = a ["b"] or {}
c = a ["b"]

c = {}
for x = 1, 9, 1 do
c[x] = 1 + x
end

print(a[c][1])


I get "error: attempt to index a nil value"

Hope you can help me,

Thanks
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #8 on Wed 17 Feb 2010 03:22 PM (UTC)
Message
print(a[c][1])


You have not assigned anything to a[c]. You've assigned a["b"] (which is the same as a.b), and you assigned a.b to c -- but then you set c to {}. Anyhow, since a[c] does not exist, you cannot index into it with [1].

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Bitttttor   Australia  (6 posts)  [Biography] bio
Date Reply #9 on Thu 18 Feb 2010 12:44 AM (UTC)

Amended on Thu 18 Feb 2010 02:08 AM (UTC) by Bitttttor

Message
Thanks David, what I want to do is to generate a table "a" which contains a sub table "b" (and maybe others, "d" and "e" for example), and feed that "b" table with a for loop to access each one of the "b" elements individually. ie.
 
print(a[b][1])

Not sure how.
[Go to top] top

Posted by Twisol   USA  (2,257 posts)  [Biography] bio
Date Reply #10 on Thu 18 Feb 2010 12:54 AM (UTC)

Amended on Thu 18 Feb 2010 12:55 AM (UTC) by Twisol

Message
Use \[b\] instead, because [b] is a forum-code for bold text. Also remember that you can edit your previous posts, there's an "edit" link in the post header.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Thu 18 Feb 2010 04:41 AM (UTC)
Message
Bitttttor said:

c = a ["b"]
c = {}


It isn't clear what you are really trying to do, but as David says, this is like saying:


c = 1
c = 2


You have totally replaced the assignment to c that you just did.

- Nick Gammon

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

Posted by Bitttttor   Australia  (6 posts)  [Biography] bio
Date Reply #12 on Thu 18 Feb 2010 07:20 AM (UTC)

Amended on Thu 18 Feb 2010 11:09 AM (UTC) by Bitttttor

Message

stores = {}   -- make table (first time)

-- create sub-table for acknor, if not already exists
stores ["acknor"] = stores ["acknor"] or {}

-- get reference to save typing
store = stores ["acknor"]

-- store details about wood
store ["wood"] = { buy = 8, stock = 130, sell = 73 }

-- and iron
store ["iron"] = { buy = 15, stock = 5, sell = 85 }


I was using this scheme but I'm starting to realize I was completely lost...

What I'm trying to do is to declare a table (i.e. mainTable) which contains two tables (i.e. subTable01 and subTable02). Then, I want each one of this two sub tables to be fed by a for loop, something like this:


subTable01 = {}
   for tIter = 1, 9, 1 do
      subTable01[tIter] = tIter
   end		
print(subTable01[2])


In other words, how can I put two or more of this "for" generated tables inside another one? and how can I access their elements? Hope is clear now. I don't know the values and I need them to be stored in order to make comparisons between them.

Cheers
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #13 on Thu 18 Feb 2010 04:01 PM (UTC)
Message
I confess that I still don't really understand what you're trying to do. Let's go back to basics for a bit. In Lua, when you do something like this:

<some expression>[<some index>]


it is only sensible if <some expression> evaluates to a non-nil object that can be indexed (in general many things, but usually just a table -- let's stay simple for now).

The expression can be anything: a function call, a variable, an indexing into another table, etc.

So, if you ever want to write:

some_table[some_key][some_other_key] = 123


then this only makes sense if some_table is indexable, and some_table[some_key] has also been assigned something that is indexable.

In other words, before you try to index into some_table[some_key], you need to make sure that you've actually put a table into some_table at the index some_key.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Thu 18 Feb 2010 07:27 PM (UTC)

Amended on Thu 18 Feb 2010 07:30 PM (UTC) by Nick Gammon

Message
Have you read my postings?

http://www.gammon.com.au/forum/?id=4903 (Lua tables)

http://www.gammon.com.au/forum/?id=6036 (Lua tables in detail)

Quote:


subTable01 = {}
   for tIter = 1, 9, 1 do
      subTable01[tIter] = tIter
   end		
print(subTable01[2])



It really isn't clear here what you are doing. For one thing, in Lua you usually don't use numeric indexes like that. There is a "pairs" function that goes from one end of the table to another.

So for example:


subtable = {}
subtable [1] = "fish"
subtable [2] = "chips"

for index, value in pairs (subtable) do
  print (index, value)
end -- for

Prints ...

1 fish
2 chips


You could do it more the way you had:


subtable = {}
subtable [1] = "fish"
subtable [2] = "chips"

for i = 1, #subtable do
  print (i, subtable [i])
end -- for


But why would you bother?

Next:

Quote:


subTable01 = {}
   for tIter = 1, 9, 1 do
      subTable01[tIter] = tIter
   end		
print(subTable01[2])



Are you trying to make a table with the keys being 1 to 9, and the value of each key also being 1 to 9? I suppose you can do that, your code works, and it prints 2. But to what purpose?

- 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.


49,134 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]