GMS 2.3+ Loop over struct's members? Check if struct has member?

Erik Leppen

Member
I'm sure this is very simple, but I couldn't find it on the manual's page about structs, so I have two very short questions about structs.

1. how do I loop over a struct's member names and values (including variables, methods and sub-structs)?

2. how do I check if a struct contains a certain member (regardless of whether it is a variable, method or sub-struct)?

Example: suppose I have a struct {a: 10, b: 20}.
For 1, I'm looking for a loop with 2 iterations, where the iterator variable is "a" on the first iteration and "b" in the second.
For 2, I'm looking for a function that, when given "a" or "b", returns true, and when given anything else, returns false.

I assume struct member names are strings, is this correct? Normally in code, I would do mystruct.a, but if I have "a" as a string, should I do mystruct["a"], or mystruct[membername] if membername is a variable?

Thanks in advance for helping me out :)
 

samspade

Member
You can loop through all a struct with the following code (you can loop backwards or forwards, this example just happens to loop backwards:

GML:
var _keys_array = variable_struct_get_names(struct);
for (var i = (array_length(_keys_array) - 1); i >= 0; i -= 1) {
    //use _keys_array[i] here
}
If you know the name of the variable you want to check for you can also use variable_struct_exists and related functions found here: https://manual.yoyogames.com/GameMa...nce/Variable_Functions/Variable_Functions.htm

There's also the struct accessor $ which you can use like this struct[$ name] where the name is a string and it will returned undefined if the variable doesn't exist.
 

FrostyCat

Member
1. You can loop through a struct's keys using variable_struct_get_names. Do note that just like with DS maps, the keys are NOT necessarily sorted by insertion order or any human-oriented order. If you want a to always come before b, use array_sort.
GML:
var keys = variable_struct_get_names(strc);
array_sort(keys, true);
for (var i = array_length(keys)-1; i >= 0; --i) {
    var key = keys[i];
    var value = strc[$ key];
    /* Use key and value here */
}
2. Use variable_struct_exists to determine for sure whether struct contains a given key. Like with DS maps, DO NOT check against undefined. The latter is a defective strategy that cannot tell between an existent entry that holds undefined and a non-existent entry.
 

Erik Leppen

Member
Thanks guys, that was what I needed. As a little test, I wrote the function below and it seems to work as expected :)

GML:
function struct_report (test_struct) {
    var names = variable_struct_get_names(test_struct);
    var nn = array_length(names);
    for (var n = 0; n < nn; n += 1) {
        var name = names[n];
        var value = variable_struct_get(test_struct, name);
        show_debug_message("test_struct[$ " + name + "] = " + string(value) + ".");
    }   
}
 
Top