Log In  


If you feel like you don't understand Lua's tables, I hope this post helps. I use tables all the time when I'm programming; they are super useful. Let's study them so you can use them too!

Tables can do several different things, which makes them a bit tricky. We'll start by exploring a common use: using tables to store a list of things, such as:

  • A hand of cards: 2♠, 3♥, Q♦, K♣, J♣
  • A list of monsters: Ogre, goblin, slime mold
  • The positions of all the black checkers: 12, 24, 20, 27

Making lists

This makes an empty list:

items={}

This makes a list with the names of some things found in a forest:

items={'tree', 'rock', 'stream'}

Now items contains 3 things; you can think of it like 3 boxes:

The first box contains 'tree', the second contains 'rock', the third contains 'stream'.

Getting items out of a list

Each box has a number, called its "index". To get the value from the first box, we do items[1] like this:

> print(items[1])
tree

We can also store the index in a variable, like this:

> current_index=1
> print(items[current_index])
tree

To pick a random item from a list, we can use rnd():

> print(rnd(items))
stream
> print(rnd(items))
tree

Changing items in a list

We can change the value stored in a box by using its index. Here's how to replace 'rock' with 'moss':

> items[2]='moss'

Length of a list

To get the number of items in a list, we use #items:

> length=#items
> print(length)
3

Here's a common way to get the last item of the list. It uses the list's length as an index:

> print(items[#items])
stream

Adding items

Items can be added to a list using add().

This adds to the end of the list:

add(items, 'mushroom') -- adds at end

This adds at the start of the list:

add(items, 'wolf', 1) -- adds at index 1

Deleting items

We can delete items by value:

del(items, 'tree')

or by index:

deli(items,2)

Looping over a list

We can access every item in a list using a for loop and all():

for item in all(items) do
 print(item)
end

That would print this:

wolf
stream
mushroom

If you need the index too, you can use a numeric for loop from 1 up to the length of the list:

for i=1,#items do
  print(i..': '..items[i])
end

That would print this:

1: wolf
2: stream
3: mushroom

Ok, that's it for lists.

Wow, that turned out longer than I expected. I also want to explore using tables to store dictionaries, but before I do, does anyone have any questions? Or feedback? Is this useful? Would it be better with more (or less) detail? Let me know what you think...

7


This is great, thank you. Even though I love using them I simply skipped the opportunity to loop through them by index instead of element. Always used a hacky way to determine what number I am on :D
I love re-reading basic tutorials to rediscover these basic things


I have a question...

Say you have a table containing the X and Y positions of objects. Now the X and Y values are randomly picked from a table of listed positions.

How would I create a loop to iterate through the table of objects and compare there X or Y positions to see if they overlap? And if they overlap how reposition the object the loop found.

I have tried nesting a for all loop inside of a counter for loop and I think I'm on the right track but it creates chaos at the moment.


Let's start with the second question: How do you pick a position that isn't already used?

Option 1: assign positions sequentially and keep track of the index of the first un-assigned position.

positions = {{1,1}, {2,2}, {3,3}}
next_position = 1
object1.position = positions[next_position]
next_position += 1
object2.position = positions[next_position]
next_position += 1

Option 2: Keep a list of unassigned positions, and remove positions from the list as you assign them.

positions = {{1,1}, {2,2}, {3,3}}
object1.position = deli(positions)
object2.position = deli(positions)

If you've already assigned some positions, you can use option 2 after you've figured out which positions are available. This is straightforward if the objects reference the same positions that are in the positions array:

available_positions={}
-- Copy all positions into available_positions
for p in all(positions) do
  add(available_positions, p)
end
-- Remove positions that are assigned
for o in all(objects) do
  del(available_positions, o.position)
end

(this code only works if you do object.position = positions[1] then this is easy because object.position == positions[1] is true. If you do object.position.x,object.position.y = positions[1].x,positions[1].y then object.position == positions[1] is false, and the del() line will have to be more complicated.)

Is that enough to get you unstuck?


(iteration needs for p in all(positions), not of)


Thanks merwok! I fixed it. I guess my head was still in TypeScript when I wrote that.


How do I compare elements of a table with other tables?

I have have some tables: a={},b={},c={}
Each one filled with some random numbers (dice rolls).
Up to a maximum of 5 entries per tables.
Sometimes less but no more than 5.

How would I put all the entries into a bigger table e={}?
So that a={1,2,3,4,5}, b={5,4,3,2,1}, c={2,4,6,1,2}
then e={1,2,3,4,5,5,4,3,2,1,2,4,6,1,2}

Then if I have another table f={4,4,4}.
How would I compare it's contents with e={}
And return true (because both f and e contain three 4s)?

Thanks for your help.
I'm new to this and struggling to get this working myself.


1

Just to make sure I understand what you're attempting, you're trying to determine if the numbers in f can be found across a, b, & c right?

Or put another way, e is the union of a, b, & c. For each number in f, you're checking whether the number of occurrences of that number in f is less than or equal to the number of occurrences of that number in e. Did I get that right?

Here's how I would approach this:

  1. Count the number of times each dice roll appears in e.
  2. Count the number of times each dice roll appears in f.
  3. For each number in f, compare the counts from step 1 and step 2.

As a shortcut, instead of generating e, I'm going to count the number of times each digit appears in a, then add the number of times each digit appears in b, then add the number of times each digit appears in c. In other words, I'll count up the digits in a, b, and c directly without making e.

This feels like a great place to use tables as dictionaries, which I didn't get to in my post above. (Would anyone find it useful if I went back and updated the post to cover dictionaries too?)

Here's a function which takes in a list of numbers (t) and a table for storing the counts (counts). It updates counts based on what is in t.

-- t: list of numbers.
-- counts: total number of
-- occurrences of each number,
-- indexed by number.
-- this function updates counts
-- based on the values in t.
function count_items(t,counts)
 for n in all(t) do
  if counts[n]==nil then
   counts[n]=0
  end
  counts[n]+=1
 end
end

If we call it on f, we end up with a table showing there are three 4's:

f={4,4,4}
f_count={}
count_items(f,f_count)
-- f_count is {4:3}

And if we call it on a, b, and c we get the following:

a={1,2,3,4,5}
b={5,4,3,2,1}
c={2,4,6,1,2}
e_count={}
count_items(a,e_count)
count_items(b,e_count)
count_items(c,e_count)
-- e_count is {1:3, 2:4, 3:2, 4:3, 5:2, 6:1}

Finally we can compare e_count and f_count:

for n,c in pairs(f_count) do
 print("does e have at least "
 		..c.." "..n.."'s?")
 if e_count[n]!=nil and 
 			e_count[n]>=c then
  print("  yes")
 else
  print("  no")
 end
end

P.S. PICO-8 has a function called count for counting the number of times an item occurs in a list. You could do something like count(a, 5) to find out how many times 5 shows up in a. There's probably a way to write count_items using count but after looking at it for a minute I couldn't figure out anything that was simpler than what I had so I left it alone.


Awesome stuff.

"you're trying to determine if the numbers in f can be found across a, b, & c right?"
That's correct.

Something similar just dawned on me when right before I read your post.
So that's great. Lots to experiment with now and figure this out. I have a feeling I got my head around it.

Thanks so much for the detailed reply!



[Please log in to post a comment]