Table Sorting in lua

Posted by Strazor on Wed 27 Aug 2014 03:28 AM — 7 posts, 27,484 views.

USA #0
I've managed to capture eqdata and invdetail (both are commands in Aaardwolf). I can capture the data with triggers and send it to an array.

When I print the array

tprint (eqipinform)

the result (I'm only posting two results out of 29)

"468263929":
  "level"=1
  "weight"=1
  "wearloc"="sleeping"
  "details_captured"=true
  "stats":
  "owner"="Strazor"
  "objectid"="12569898"
  "flags"="glow, hum, magic, held, nopurge, burn-proof, nolocate, solidified, resonated, illuminated, v3, precious"
  "itemtype"="Furniture"
  "container_id"="worn"
  "resists":
  "name"="V3 Trivia Sleeping Bag"
  "score"="0"
"965742031":
  "level"=41
  "weight"=0
  "wearloc"="neck"
  "details_captured"=true
  "stats":
    "damageroll"=29
    "luck"=2
    "moves"=-30
    "wisdom"=2
    "intelligence"=2
    "hitroll"=1
    "hitpoints"=25
  "owner"=""
  "objectid"="125689755"
  "flags"="unique, glow, hum, magic, held, burn-proof, solidified, illuminated, v3, searchable"
  "itemtype"="Armor"
  "container_id"="worn"
  "resists":
  "name"="(>Asura's Azurite Pearl<)"
  "score"="205"

Here is where I've lost visualization. How do I extract custom data from the table? For instance, damage roll, hit roll, etc.

I've tried the following:

table.foreach (equipinform, print)

and got the following result:

468263934 table: 0x026387e0
965742678 table: 0x01858e20
630298213 table: 0x0223a8c8
965731907 table: 0x021fb3f8
965752670 table: 0x0244bcf8
748863834 table: 0x0264fe68
118730246 table: 0x0240fc00
973922268 table: 0x02481068
468233209 table: 0x0222e040
973922349 table: 0x016dd7f8
965751034 table: 0x0184abe0
428935134 table: 0x026f1288
505208345 table: 0x023bacc0
131909345 table: 0x024dd0e8
468156345 table: 0x026d8d18
973922335 table: 0x0240d570
423542987 table: 0x025f44d0
965753789 table: 0x0170bd90
168525345 table: 0x02482288
553988345 table: 0x02386028
504820454 table: 0x0265eee8
553987564 table: 0x0265e6c0
965729234 table: 0x01049858
485890789 table: 0x023cb4c8
965761345 table: 0x026c6fa8
965752233 table: 0x02481478
945724244 table: 0x024485b8
522889566 table: 0x02448790
965731567 table: 0x024834c8

The numbers in the left column are equipment ID numbers.

I have reviewed http://www.gammon.com.au/forum/?id=6036 (What are tables?) but did not have any success. Any help is much appreciated and I'm looking forward to learning something new.
Australia Forum Administrator #1
You have tables within tables here, so you need to go down a level or two.

To reproduce your test data I made this table:


equipinform = {

["468263929"] = {
    level=1,
    weight=1,
    wearloc="sleeping",
    details_captured=true,
    stats = {},
    owner="Strazor",
    objectid="12569898",
    flags="glow, hum, magic, held, nopurge, burn-proof, nolocate, solidified, resonated, illuminated, v3, precious",
    itemtype="Furniture",
    container_id="worn",
    resists = {},
    name="V3 Trivia Sleeping Bag",
    score="0",
    },

["965742031"] = {
    level=41,
    weight=0,
    wearloc="neck",
    details_captured=true,
    stats = {
      damageroll=29,
      luck=2,
      moves=-30,
      wisdom=2,
      intelligence=2,
      hitroll=1,
      hitpoints=25,
      },
    owner="",
    objectid="125689755",
    flags="unique, glow, hum, magic, held, burn-proof, solidified, illuminated, v3, searchable",
    itemtype="Armor",
    container_id="worn",
    resists = {},
    name="(>Asura's Azurite Pearl<)",
    score="205",
    }

} -- end of equipinform

tprint (equipinform)


Now to go through it:


print (string.rep ("-", 70))

-- go through each item
for k, v in pairs (equipinform) do
  print ""
  print ("Doing item", k)
  local stats = v.stats  
  local resists = v.resists
  tprint (stats)
  
  print ("This item (" .. v.name .. ") has a damageroll of", stats.damageroll)
end -- for each item


Output:


Doing item 965742031
"hitpoints"=25
"luck"=2
"damageroll"=29
"hitroll"=1
"wisdom"=2
"intelligence"=2
"moves"=-30
This item ((>Asura's Azurite Pearl<)) has a damageroll of 29

Doing item 468263929
This item (V3 Trivia Sleeping Bag) has a damageroll of nil


This isn't exactly "sorting" but it is extracting. If you want to sort you might want to specify what you want to sort on, and what happens if one of the values is nil. For example "V3 Trivia Sleeping Bag" has a damageroll of nil, so it will be hard to sort that.
Australia Forum Administrator #2
To sort the table into some order you need a table numerically keyed. We can make one with the keys of the main table, like this:


print (string.rep ("=", 70))

ts = {} -- sorted table

-- make table of keys
for k, v in pairs (equipinform) do
  table.insert (ts, k)
end -- for each item

-- sort by name
table.sort (ts, function (a, b) return equipinform [a].name < equipinform [b].name end)

-- print table in name order
for k, v in ipairs (ts) do
  item = equipinform [v]
  print (item.name)
end -- for


Our second table (ts) is just a table which records the keys in the main table. Now we can sort that, passing a custom sort function. That dereferences the main table, compare "less than" for each name.

Then we can print the items in name order. You could do that for virtually anything (eg. level) if you allow for the possibility that some values might be nil.
Amended on Wed 27 Aug 2014 06:29 AM by Nick Gammon
USA #3
Nick-

This is an invaluable lesson. Thank you for taking the time to explain this. I was able to extract the data and you added a nice tip for sorting.

Now that I can extract what is needed, how can the data be printed to express a table format with lines and column names? I am wanting to print the table data and format it with table lines and a column headers.

I would like the printed data to be expressed in a structured more readable format. An crude example is:


___________________________
                          
| item |  Level | HR | DR |
|------|--------|----|----|
| name |   42   | 15 |  5 |
|------|--------|----|----|
| name |    2   | 23 |  6 |
|------|--------|----|----|
___________________________




NOTICE Subject Change:

Can you point me to a reference discussing how to check if a variable matches a number set? If I have a variable that can range from 1 - 400. The below code is a representation of how I visualize the information, not the actual code. Once I read a bit more and realized that OR can be used it made all the difference.

if variable matches 1 - 99 then
     Note("Match 1 - 99: \""..variable.."\"")
elseif variable matches 100 - 199
     Note("Match 100 - 199: \""..variable.."\"")
elseif variable matches 200 - 400
     Note("Match 200 - 400: \""..variable.."\"")
else
    Note("No Match")
end


EDIT UPDATE: Matching Range issue | Solved

Here is my solution:

if variable  == 1 or variable <=99 then
     Note("Match 1 - 99: \""..variable.."\"")
elseif variable == 100 or variable <= 199
     Note("Match 100 - 199: \""..variable.."\"")
elseif variable == 200 or <= 400
     Note("Match 200 - 400: \""..variable.."\"")
else
    Note("No Match")
end


Much Thanks.
Amended on Wed 27 Aug 2014 03:46 PM by Strazor
Australia Forum Administrator #4
Those really should be "and" not "or". Plus you can use one quote in a string if you start with the other one. Like this:


if variable >= 1 and variable <= 99 then
     Note('Match 1 - 99: "' .. variable .. '"')
elseif variable >= 100 and variable <= 199 then
     Note('Match 100 - 199: "' .. variable .. '"')
elseif variable >= 200 and variable <= 400 then
     Note('Match 200 - 400: "' .. variable .. '"')
else
    Note("No Match")
end
USA #5
Thanks Nick. I corrected my error.

Any suggestions on the displaying of table data?
USA #6
Great news. After a bit of reading today I figured out out.


print (string.format ("%-5s %.25s", item.level, item.name))


Thanks again Nick.