myarray = {"one", "two", "three", "four"}or
mystruct = {fname="Barack", lname="Obama", job="President}or
myemptytable = {}You can then add elements by name, or with numbered elements, by number or by appending:
mystruct["party"] = "Democratic"Note the key is surrounded by quotes in the preceding. If it weren't, party would be taken to be a variable. Lua provides an alternate syntax to make things easier (alternate syntaxes to make things easier are called "syntactic sugar"):
mystruct.party = "Democratic"As far as numbers, you can use either the 2 argument insert() or use array notation with square brackets.
#!/usr/bin/luaYou create an empty table, assign element 1, and then print element 1, giving you exactly the output you expect:
mytable = {} -- make empty table
mytable[1] = "one" -- assign "one" to its element 1
print(mytable[1]) -- print element number 1
slitt@mydesk:~$ ./test.luaIn the preceding example, you had to make the empty table. If you'd just tried to assign element 1 to a non-table variable, you'd have gotten a "attempt to index global 'mytable' (a nil value)" error.
one
slitt@mydesk:~$
#!/usr/bin/lua
mytable = {"one", "two", "three"}
print(mytable[2]) -- print element number 1
#!/usr/bin/luaThe preceding prints the following:
myarray = {"one", "two", "three", "four"}
myarray[5] = "five"
table.insert(myarray, "six")
for k, v in pairs(myarray) do
print(string.format("k=%s, v=%s", tostring(k), tostring(v)))
end
slitt@mydesk:~$ ./test.lua
k=1, v=one
k=2, v=two
k=3, v=three
k=4, v=four
k=5, v=five
k=6, v=six
slitt@mydesk:~$
president = {fname = "Barack", lname = "Obama", from = 2009, to = nil}Let's show a few presidents:
presidents = {Now let's add another president:
{fname = "Barack", lname = "Obama", from = 2009, to = nil},
{fname = "George", lname = "Bush", from = 2001, to = 2008},
{fname = "Bill", lname = "Clinton", from = 1993, to = 2000},
{fname = "George", lname = "Bush", from = 1989, to = 1992}
}
presidents.insert(Does this look like a database table to you? It sure does to me. But it's implemented as a table of tables, where the top level table has numeric keys 1 through 5, and each of the lower level tables has the same four keys, but with different values for the keys. Because the top level table has all integer keys, you can sort it with table.sort() using fname, lname, from or to to sort by. You can also iterate through the top table and then print each "column" for each element of the top level table.
{fname = "Ronald", lname = "Reagan", from = 1981, to = 1988}
)
#!/usr/bin/luaThe preceding code produces the following output:
sf = string.format
-- DEFINE TABLE WITH WORD KEYS
earthquakes = {
date8 = "1992/01/17",
date7 = "1971/02/09",
date6 = "2010/04/04",
date5 = "1987/10/19"
}
-- CONVERT TO TABLE WITH NUMERIC KEYS
earthquakes_numeric = {}
for k,v in pairs(earthquakes) do
table.insert(earthquakes_numeric, {key=k, value=v})
end
-- READ THEM BACK
for i, v in ipairs(earthquakes_numeric) do
print(sf("Row %d, key=%s, value=%s",i, v.key, v.value))
end
-- SORT THEM
table.sort(earthquakes_numeric, function(a,b) return a.value < b.value end)
print("=====================")
-- READ THEM BACK AGAIN
for i, v in ipairs(earthquakes_numeric) do
print(sf("Row %d, key=%s, value=%s",i, v.key, v.value))
end
slitt@mydesk:~$ ./test.luaSo that's it. That's how you can sort a table with named keys -- you simply make each key/value pair an element in a table with numeric keys.
Row 1, key=date6, value=2010/04/04
Row 2, key=date8, value=1992/01/17
Row 3, key=date5, value=1987/10/19
Row 4, key=date7, value=1971/02/09
=====================
Row 1, key=date7, value=1971/02/09
Row 2, key=date5, value=1987/10/19
Row 3, key=date8, value=1992/01/17
Row 4, key=date6, value=2010/04/04
slitt@mydesk:~$
#!/usr/bin/luaThe preceding creates a table with keys 1 through 4, 6 (skipping 5), float 1.5 and string "name". What it should do is iterate through keys 1 through 4, skipping 1.5 because 1.5 is not an integer, and stopping at 4 because 5 is undefined. It also doesn't iterate key "name" because it's a string, not an integer. So the preceding should print "one", "two", "three" and "four". Let's see if it does:
local mytable = {"one", "two", "three"}
mytable[4] = "four"
mytable[6] = "six" --notice the gap at 5
mytable["name"] = "Steve" --notice this is a string, not an integer
mytable[1.5] = "one-point-five" --notice this is a float, not integer
for k, v in ipairs(mytable) do
print(string.format("k=%s, v=%s",tostring(k),tostring(v)))
end
slitt@mydesk:/d/websites/tjunct/codecorn/lua$ ./test.luaThere it is -- ipairs() worked just as specified.
k=1, v=one
k=2, v=two
k=3, v=three
k=4, v=four
slitt@mydesk:/d/websites/tjunct/codecorn/lua$
slitt@mydesk:/d/websites/tjunct/codecorn/lua$ ./test.luaYou can see it printed every key and value. It just so happens the numeric keys were printed first and printed in order. DON'T COUNT ON THAT, IT WON'T ALWAYS WORK!!!
k=1, v=one
k=2, v=two
k=3, v=three
k=4, v=four
k=6, v=six
k=name, v=Steve
k=1.5, v=one-point-five
slitt@mydesk:/d/websites/tjunct/codecorn/lua$
presidents = {You could set up an index table whose each element is has the "from" year as a key, and the record number in the presidents table as the value. So you look for the year as a key in the index table, and look in the presidents table for the element whose key is the value from the index table, and bang, you've looked it up by year. Of course this works only if each element's from year is unique. Otherwise you'd need to do things differently.
{lname = "Obama", fname = "Barack", from = 2009, to = nil},
{lname = "Bush", fname = "George W", from = 2001, to = 2008},
{lname = "Bush", fname = "George HW", from = 1989, to = 1992},
{lname = "Clinton", fname = "Bill", from = 1993, to = 2000}
}
#!/usr/bin/luaThe preceding code outputs the following:
sf = string.format
ts = tostring
-- MAKE LIST OF LAST FOUR PRESIDENTS IN NO SPECIAL ORDER
presidents = {
{lname = "Obama", fname = "Barack", from = 2009, to = nil},
{lname = "Bush", fname = "George W", from = 2001, to = 2008},
{lname = "Bush", fname = "George HW", from = 1989, to = 1992},
{lname = "Clinton", fname = "Bill", from = 1993, to = 2000}
}
-- CREATE A LOOKUP INDEX FOR from YEAR
pres_from_idx = {}
for k, v in ipairs(presidents) do
pres_from_idx[v.from] = k
end
-- PRINT EVERYTHING FOR THE GUY WHO SERVED FROM 1993
print("==== FOLLOWING IS INFO FOR PRESIDENT STARTING IN 1993 ====")
prez = presidents[pres_from_idx[1993]]
for k, v in pairs(prez) do
print(sf(" %s=%s",ts(k), ts(v)))
end
-- MAKE INTEGER KEY TABLE OF FROM YEARS
year_array = {}
for k, v in pairs(pres_from_idx) do
table.insert(year_array, k)
end
-- SORT THE INTEGER KEY TABLE
table.sort(year_array, function(a,b) return a < b end)
-- PRINT PRESIDENTS IN CHRONOLOGICAL ORDER
print("\n==== FOLLOWING IS CHRONOLOGICAL LISTING OF PRESIDENTS ====")
for k, v in ipairs(year_array) do
yearstarted = v
recno = pres_from_idx[yearstarted]
prez = presidents[recno]
print(sf(" %s %s served from %s to %s",
prez.fname, prez.lname, ts(prez.from), ts(prez.to)))
end
slitt@mydesk:~$ test.luaOf course, when there is a possibility of duplicates, you must make different arrangements. For instance, perhaps each key in the index will have a value that is an array-like table of all the record numbers in the original table that have that key. Or, perhaps you can have an array like index table, with each element being a table with a key and a record number, and then sort that array like index table. These possibilities will remain as exercises for you. The point is, any time you need quick lookup on a table, especially a large one, you can create a second table that serves as an index to the first. And one way or another, you can build another table sorted on a specific information piece from the first table.
==== FOLLOWING IS INFO FOR PRESIDENT STARTING IN 1993 ====
fname=Bill
to=2000
lname=Clinton
from=1993
==== FOLLOWING IS CHRONOLOGICAL LISTING OF PRESIDENTS ====
George HW Bush served from 1989 to 1992
Bill Clinton served from 1993 to 2000
George W Bush served from 2001 to 2008
Barack Obama served from 2009 to nil
slitt@mydesk:~$
[ Troubleshooters.com| Code Corner | Email Steve Litt ]
Copyright (C) 2011 by Steve Litt --Legal