MarkUp 5/Arrays vs. Lists

The concept of arrays is basic and familiar to the majority of the programming languages out there. An array is a variable that is capable of storing multiple values, according to its index – which could be 1-dimensional or 2-dimensional in Game Maker.

However, Game Maker contains an excellent data structure – lists. A list is always 1-dimensional, and contains different values (sorted or not). Many other data structures exist in Game Maker, such as stacks and queues. What makes lists special is that it has direct-access, as opposed to their sequential access.

It might be easy to establish how arrays differ from regular variables, and how lists differ from other data structures. But the real question is: when to use lists, and when to use arrays – and which is better?

Understanding the Differences
To be able to wisely choose which method to use for a particular case, the differences between lists and arrays must be established. First, a clear advantage of arrays over lists is ability of using 2-dimensional arrays to form ‘tables’. Lists particularly fail at this, and storing multiple variables in a “row” might lead to the need for string manipulations, or other tricks.

The use of CSV files to store data has been covered in the previous issue of MarkUp, and such an application is better implemented with arrays.

However, lists have their own advantages as well. First of all – according to Mark – handling lists is much faster and resource-friendly than arrays. So if you care about speed, lists have a good advantage. Not only that, but lists also can have data inserted to them in the middle, added to the end, sorted and re-sorted at any time, and more. Lists just fascinate me!

The major disadvantage of lists is that they are not saved with the game! So if you’re game utilizes save/load, you’ll either have to make your own save mechanism (like I did for one of my projects), or just make a script that loads the list after loading the game.

On the upside, though, Game Maker already provides reading and writing functions for lists, so you can easily save scripts to files and load them.

Where Lists Shine
I’ve mentioned the good points of lists in short before, but here’s some info about what’s really great about lists:

Copying Lists
A list could be copied from one id to another. This could hardly be achieved by arrays – but with lists, it only requires a single quick function. Copying a list is more useful than it seems, but its applications depend on the way you’re using the lists in the first place.

For example, a list could be used to store multiple copies with multiple arrangements. Such an application allows a host of things to be done, including simple procedures such as finding the mode of values.

A more specific example is something like a “soccer tournament”. We see in all FIFA games how teams are drawn up – such that teams in the quarterfinals, semi-finals, and finals are all displayed.

This could also be done by copying a list of participants to other lists, and removing unqualified teams. Another application is the use of “indexing”, so that a long list is copied to different smaller lists, and all the list items except for those starting from a particular letter are removed. This results in having smaller lists, each having values starting with a single letter. When those are further sorted, they could be used in an index-like atmosphere, such as a dictionary.

Getting List Size
When using arrays, we almost always have to include another variable that acts as a “counter”, so that the game only performs certain operations on the number of items that are there in an array. A list eliminates the need for such variable.

Easy Insertion of Values
Easy insertion of values to scripts is one of the things I LOVE about them! To properly insert a variable in an array, a loop should be performed to move all items occurring on or after the point of insertion one further step. This is all done automatically with lists, and not only that, but also much faster (in terms of execution speed).

Easy Removal of Values
Once a value is deleted from a list, all values fix their positions. Basically, it is the reverse of “Easy Insertion of Values”, something that also isn’t natively available for arrays.

Searching Capabilities
The searching capabilities for lists are extremely useful. You can find the value of a list row from its position, or get that list’s ID by writing its value. Both give great possibilities, especially when used in conjunction with other list functions, such as sorting. You can find the nearest instance from a particular object, etc.

Sorting
One of my favorites! You can sort all values in a script either ascending or descending. This also works for both numbers and text pretty well. This is pretty useful when using the list data structure to draw and actual list on the screen, which could become long.

Shuffling
I’m in LOVE with shuffling. It has so many uses, ranging from the obvious “cards” to the AI for strategy games, or the order of events in a timeline for another.

Tables
Though variable[4] arrays could be useful, something I really like about arrays is the use of two-dimensional arrays, like this variable[6,3], to locate a value’s position both on x and y. The use of two-dimensional arrays as tables is very interesting but will not be discussed in any further detail in this article.

Changing Values
Changing the fourth row of the array “variable” from 5 to 6 is pretty simple in arrays. A simple line of code: variable[4] = 6; But in lists, a ds_list_replace function needs to be called, and the position of the row needs to be known (since with insertion and sorting, it’s constantly changing) using yet another ds_list_find_index function. So it could be pretty painful at times.

Conclusion
Though lists could be used for everything, and arrays could be used for everything – some things are better handled by one mechanism than the other. Everything could be achieved, but when the results are the same, you might have to consider what is easier and quicker to write, and which is faster to execute.