Parsing/printing from Lua table

Posted by Stacy_19201325 on Tue 04 Mar 2014 05:29 PM — 5 posts, 20,072 views.

#0
I'll start by apologizing for not being a programmer. I had some C++ in high school, more than a decade ago.

The server administrator of a game I play has provided a Lua file listing current in-spawn resources, and I want to be able to print the data I want into a format I want. Here's what the table looks like (only a small portion from the beginning):

resources = {
	{
		name = "Abacadulis",
		type = "petrochem_fuel_solid_unknown",
		classes = {
			{"Inorganic", "inorganic"},
			{"Mineral", "mineral"},
			{"Solid Petrochem Fuel", "fuel_petrochem_solid"},
			{"Unknown Solid Petrochem Fuel", "petrochem_fuel_solid_unknown"},
		},
		attributes = {
			{"res_decay_resist", 904},
			{"res_potential_energy", 297},
			{"res_quality", 35},
		},
		zoneRestriction = "",
		surveyToolType = 6,
		containerCRC = 2431128978,
	},

	{
		name = "Abam",
		type = "fruit_flowers_talus",
		classes = {
			{"Organic", "organic"},
			{"Flora Resources", "flora_resources"},
			{"Flora Food", "flora_food"},
			{"Seeds", "seeds"},
			{"Fruit", "fruit"},
			{"Flowers", "fruit_flowers"},
			{"Talusian Flower Fruit", "fruit_flowers_talus"},
		},
		attributes = {
			{"res_decay_resist", 284},
			{"res_flavor", 686},
			{"res_potential_energy", 204},
			{"res_quality", 845},
		},
		zoneRestriction = "talus",
		surveyToolType = 3,
		containerCRC = 1349101341,
	},




and it goes on and on and on like that.


What I want to output is:

Ababuglu,Conductive Borcarbitic Copper,184,539,906,86,349,469,344,598
Abam,Talusian Flower Fruit,284,686,204,845

So, basically:

Print the value of the key “name”
Print a comma
Print the second-to-last string in the “classes” key
Print each of the numbers in the attributes key, preceded by a comma


I'm sure it's not mega complicated for someone who knows what they're doing, so can anyone point me in the right direction? I'm not sure if the "things" after classes & attributes are considered subtables. There are no = signs, so I don't know.
Australia Forum Administrator #1
The first thing is to analyze your tables. You clearly have some tables within tables. To see the structure better you can "tprint" (table print) them using the supplied tprint utility. ie.


resources = {
	{
		name = "Abacadulis",
		type = "petrochem_fuel_solid_unknown",
		classes = {
			{"Inorganic", "inorganic"},
			{"Mineral", "mineral"},
			{"Solid Petrochem Fuel", "fuel_petrochem_solid"},
			{"Unknown Solid Petrochem Fuel", "petrochem_fuel_solid_unknown"},
		},
		attributes = {
			{"res_decay_resist", 904},
			{"res_potential_energy", 297},
			{"res_quality", 35},
		},
		zoneRestriction = "",
		surveyToolType = 6,
		containerCRC = 2431128978,
	},

	{
		name = "Abam",
		type = "fruit_flowers_talus",
		classes = {
			{"Organic", "organic"},
			{"Flora Resources", "flora_resources"},
			{"Flora Food", "flora_food"},
			{"Seeds", "seeds"},
			{"Fruit", "fruit"},
			{"Flowers", "fruit_flowers"},
			{"Talusian Flower Fruit", "fruit_flowers_talus"},
		},
		attributes = {
			{"res_decay_resist", 284},
			{"res_flavor", 686},
			{"res_potential_energy", 204},
			{"res_quality", 845},
		},
		zoneRestriction = "talus",
		surveyToolType = 3,
		containerCRC = 1349101341,
	},
}

require "tprint"

tprint (resources)


Output:


1:
  "classes":
    1:
      1="Inorganic"
      2="inorganic"
    2:
      1="Mineral"
      2="mineral"
    3:
      1="Solid Petrochem Fuel"
      2="fuel_petrochem_solid"
    4:
      1="Unknown Solid Petrochem Fuel"
      2="petrochem_fuel_solid_unknown"
  "type"="petrochem_fuel_solid_unknown"
  "name"="Abacadulis"
  "surveyToolType"=6
  "attributes":
    1:
      1="res_decay_resist"
      2=904
    2:
      1="res_potential_energy"
      2=297
    3:
      1="res_quality"
      2=35
  "containerCRC"=2431128978
  "zoneRestriction"=""
2:
  "classes":
    1:
      1="Organic"
      2="organic"
    2:
      1="Flora Resources"
      2="flora_resources"
    3:
      1="Flora Food"
      2="flora_food"
    4:
      1="Seeds"
      2="seeds"
    5:
      1="Fruit"
      2="fruit"
    6:
      1="Flowers"
      2="fruit_flowers"
    7:
      1="Talusian Flower Fruit"
      2="fruit_flowers_talus"
  "type"="fruit_flowers_talus"
  "name"="Abam"
  "surveyToolType"=3
  "attributes":
    1:
      1="res_decay_resist"
      2=284
    2:
      1="res_flavor"
      2=686
    3:
      1="res_potential_energy"
      2=204
    4:
      1="res_quality"
      2=845
  "containerCRC"=1349101341
  "zoneRestriction"="talus"


As each sub-table is indented by two spaces you can see the structure better.

Tables consist of key/value entries, as described here:

http://www.gammon.com.au/forum/?id=4903

and here:

http://www.gammon.com.au/forum/?id=6036

Keys and values can be any data type except nil. Typically they are strings or numbers.

Here the keys are strings:


name = "Abacadulis",
type = "petrochem_fuel_solid_unknown",


And here they are numbers:


		classes = {
			{"Inorganic", "inorganic"},
			{"Mineral", "mineral"},
			{"Solid Petrochem Fuel", "fuel_petrochem_solid"},
			{"Unknown Solid Petrochem Fuel", "petrochem_fuel_solid_unknown"},
		},


In the absence of a specific key Lua allocates a number (starting at 1) and going up by 1 each time.

Hence the above appears as:


  "classes":
    1:
      1="Organic"
      2="organic"
    2:
      1="Flora Resources"
      2="flora_resources"
    3:
      1="Flora Food"
      2="flora_food"
    4:
      1="Seeds"
      2="seeds"
    5:
      1="Fruit"
      2="fruit"
    6:
      1="Flowers"
      2="fruit_flowers"
    7:
      1="Talusian Flower Fruit"
      2="fruit_flowers_talus"


Each class is numbered, and within each class each item is numbered.

So, since the resources are not numbered we can use ipairs to iterate through them. eg


for k, v in ipairs (resources) do
  print (k, v.name)
end -- for


Output"


1 Abacadulis
2 Abam


Quote:

Print the second-to-last string in the “classes” key


Classes is numbered, and the max will be #classes, so we can try this:


for k, v in ipairs (resources) do
  Tell (v.name)
  Tell (",")
  Tell (v.classes [#v.classes] [1])  -- last class, first string in it

  print ()  -- new line
end -- for


Output:


Abacadulis,Unknown Solid Petrochem Fuel
Abam,Talusian Flower Fruit


As for the numbers, well I'll let you try that. You need to iterate through attributes, and get the second one for each one. I'll get you started:


-- do each resource
for k, res in ipairs (resources) do
  Tell (res.name)
  Tell (",")
  Tell (res.classes [#res.classes] [1])
  Tell (",")

  -- do each attribute
  for i, attrib in ipairs (res.attributes) do
    Tell (attrib [1])
    Tell (",")
  end -- for

  print ()  -- new line
end -- for



Output:


Abacadulis,Unknown Solid Petrochem Fuel,res_decay_resist,res_potential_energy,res_quality,
Abam,Talusian Flower Fruit,res_decay_resist,res_flavor,res_potential_energy,res_quality,


It isn't exactly what you asked for but you should be able to work with that.
#2
Thank you, explaining that the keys are numbers made it so much easier to understand!

I do think I can modify that last bit of code to make it do what I want...if I could figure out how to make it run at all. I pasted your little bit of code:

Quote:
for k, v in ipairs (resources) do
Tell (v.name)
Tell (",")
Tell (v.classes [#v.classes] [1]) -- last class, first string in it

print () -- new line
end -- for


into my .lua file, below the table, and saved it, then tried to run it using the lExecutor with Lua for Windows, and it tells me:

Error during script initialization.
attempt to call global 'Tell' (a nil value)


Am I perhaps trying to run this using the wrong program, or am I missing something very important? I also downloaded the MUSHclient application, but I don't know how to use it for what I'm trying to do!
#3
Never mind, all is solved. I changed things up as well and got it to write to a text file.

local file = io.open("Spawns.txt", "w")
-- do each resource
for k, res in ipairs (resources) do
  file:write(res.name)
  file:write(",")
  file:write(res.classes [#res.classes] [1])

  -- do each attribute
  for i, attrib in ipairs (res.attributes) do
    file:write(",")
	file:write(attrib [2])
  end -- for
  file:write("\n")
end -- for
file:close()


Prints
Abacadulis,Unknown Solid Petrochem Fuel,904,297,35
Abam,Talusian Flower Fruit,284,686,204,845


Thank you SO MUCH for your help. I never could have figured it out alone.
Australia Forum Administrator #4
No worries.

Yep, "Tell" is a MUSHclient function. Running on "native" Lua file:write would be the way to go.