Merging Lua Tables

Dec. 06 2020

In the previous article we discussed using a Save Module in our Love2D games. Remember how we had a potentially ginourmous lua table of game data, but would sometimes only want to update just a portion? We could (like in the last article) update the table by updating it directly like so:

SAVE.player.attr.hp = 100
SAVE.checkpoint = { area ='A2', col = 3, row = 4 }

Then persist the entire table:

saveGame(SAVE)

This works, and really isn't so bad. It's actually pretty efficient. We are giving direct access to the index of the value we wish to update. So why should we continue? Well we are humans, and although we may not admit it, we take order over efficiency any day of the week. In other words, we'd rather spend a few extra CPU cycles to make our code readable, so when we revisit our code a couple years later we'll remember why it works the way it does.

Here's how I'd like to save my data:

saveGame({
   player = { attr = { hp = 10 }},
   checkpoint = { area = 'A2', col = 3 },
})

So now you're saying, "well that isn't completely different, and it's uglier!" Two things:

  1. To me it reads better, as in "please save this data for me" and the saveGame takes care of it.
  2. Notice how I just want to update checkpoint.area and checkpoint.col (we want checkpoint.row to stay the same). We simply ignore it, cause our new values will be merged in.

Merging Tables

For merging tables in lua we use a for loop. The below method will overwrite conflicting indices in t1 with values from t2, plus add any new indices from t2.

-- merge two tables, in place
function merge(t1, t2)
        for k, v in pairs(t2) do
                t1[k] = v
        end

        return t1
end

One problem here is we are using nested tables. If we were to use this method we'd corrupt our game data! Let's update our code to handle nested tables:

-- merge two nested tables, in place
function merge(t1, t2)
        for k, v in pairs(t2) do
                if type(v) == 'table' then
                        t1[k] = merge(t1[k], t2[k])
                else
                    t1[k] = v
                end
        end

        return t1
end

This is better! Our t1 table has been updated only with the values we've provided.

Our Save Module

Below is our Save Module and updated usage case:

Conclusion

We talked about merging tables in Lua, and how to leverage it with saving data for our Love2D game in a more readable, intuitive approach. Thanks for reading!