1. Hey! Guest! The 33rd GMC Jam will take place between May 23rd, 12:00 UTC (Friday noon) and May 27th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

Initialize an Array in One Line?

Discussion in 'Programming' started by NQShabazz, Aug 9, 2016.

  1. NQShabazz

    NQShabazz Member

    Joined:
    Jun 23, 2016
    Posts:
    3
    In GML, is it possible to cleanly declare and initialize an array in one line?
    Something like:
    Code:
    var myArray = {0, "lol", 244, c_white};
    ?

    Although on second thought, I can always make a script for this, I'd like to know if GML has anything built-in.
     
    Bentley likes this.
  2. TsukaYuriko

    TsukaYuriko Q&A Spawn Camper Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    1,253
    No.
     
    Bentley and Freddy Jones like this.
  3. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    yes you can.

    make a script called array.
    Code:
    ///array(*args);
    var arr;
    for (var i=0;i<argument_count;i+=1)
    {
        arr[i] = argument[i];
    }
    return arr;
    var my_array = array(0, "lol", 244, c_white);

    TADAAA!!!!

    there are many work around's for GM's shortcomings
     
  4. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    693
    I use a string parser for declaring most of my arrays (unless I need to squeeze the program for speed), there's this one:

    Code:
    /// string_split_ext(string, *delimiter) = array;
    
    var str = argument[0],
      delim = "|";
    
    var arr = 0,
      c1 = 0,
      p1 = 0;
    
    if (str == "")
    {
      return undefined;
    }
    
    if (argument_count >= 2)
    {
      delim = argument[1];
    }
    
    do
    {
      var temp = "";
      
      p1 = string_pos(delim, str);
      
      if (p1 == 0)
      {
      temp = str;
      }
      else
      {
      temp = string_copy(str, 1, p1 - 1);
      
      str = string_delete(str, 1, p1);
      }
      
      if (string_char_at(temp, 1) == "$")
      {
      temp = string_delete(temp, 1, 1);
      }
      else
      {
      temp = real(temp);
      }
      
      arr[c1++] = temp;
    } until (p1 == 0)
    
    return (arr);
    
    ... Which can be used like this:

    Code:
    my_array = string_split_ext("$Hello World!|999|$stainedofmind|0|1|2|3|4|$$5.99");
    
    ... Where it will return any value starting with '$' as a string, otherwise it will be a real. The last value in the example will also be a string equal to '$5.99'. The problem with this if course is string breaking to add variable values, resource IDs, and running scripts and equations, so I typically use the above in conjunction with a simple script I call 'strf', as below:

    Code:
    /// strf(str, arguments) = new_str;
    
    var str = argument[0];
    
    var c1 = 1;
    
    repeat (argument_count - 1)
    {
      str = string_replace_all(str, "$" + string(c1 - 1), string(argument[c1]));
      
      c1++;
    }
    
    return (str);
    
    ... Which simply replaces all instances of '$x' with the matching value in the arguments, like this:

    Code:
    player_name = "stainedofmind";
    greeting = strf("Hello, $0!", player_name);
    
    ... So a combination would be:

    Code:
    player_name = "stainedofmind";
    my_array = string_split_ext(strf("$Hello, $0!|999|$$0|0|1|2|3|4|$$5.99", player_name));
    
    ... Of course, careful inspection of the code would show that the last entry could be modified if 6 or more arguments are given to strf. My solution would be to just provide it as an argument itself, like this (just pretend I actually use the extra arguments...):

    Code:
    player_name = "stainedofmind";
    my_array = string_split_ext(strf("$Hello, $0!|999|$$0|0|1|2|3|4|$$6", player_name, 0, 1, 2, 3, 4, "$5.99", "Butts"));
    
    .... Anyway, enough ranting. Use these scripts if you like. One of these days I'll probably just make a combined version of these scripts if I keep using them as much as I have been lately. Maybe even with escape characters.
     
    Abrexas, elementbound and NQShabazz like this.
  5. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    That may work. It is far more expensive than the array script I posted. If you plan on using alot of arrays you should not parse a string each time as he says. I think you both would benefit from the array script =P

    EDIT; it is also good to note that 1d arrays are the same as 2d arrays in GMS. A "1d" array just defaults the second dimension to 0.
     
  6. NQShabazz

    NQShabazz Member

    Joined:
    Jun 23, 2016
    Posts:
    3
    That's a lot to do to make an array 0_0. Still, that's pretty good for maybe reading files at the start of the program
     
  7. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,512
    var array; array[0] = 1 array[1] = 2 array[2] = 3 array[3] = 4 array[4] = "I" array[5]="declare" array[6]="a" array[7]="thumb" array[8]="war!";

    There, all one line. :p
     
    Monsi, renex, Dengar and 3 others like this.
  8. Yal

    Yal Member GMC Elder

    Joined:
    Jun 20, 2016
    Posts:
    3,312
    Or even better...
    upload_2016-8-9_21-35-27.png
     
    Dotch, Salvakiya and Abrexas like this.
  9. elementbound

    elementbound Member

    Joined:
    Jun 30, 2016
    Posts:
    114
    To add to Yal's answer: It's better to start at the end of the array, because that way GMS will reserve the memory needed for the whole array in one go. If you were to start from the beginning, the array would have to be resized each iteration to grow.
     
  10. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    693
    I am aware of the overhead in the method I posted, and I do have a series of scripts to work directly with arrays, but those are limited to the 16 arguments of a script, where the one I posted (save for the strf portion) is limited only by the maximum string length... And deliminator character of course!
     
    Abrexas and elementbound like this.
  11. TsukaYuriko

    TsukaYuriko Q&A Spawn Camper Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    1,253
    This is not true for HTML5 and JS targets.
    https://www.yoyogames.com/blog/63
     
    Salvakiya and elementbound like this.
  12. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    If I were to do that though I would just write my values in Json and make a map to array script. then you can just used json_decode to decode the json data.

    Edit:
    Freddy Jones fixed this jarray script
    Code:
    ///jarray(json_list)
    var map = json_decode(argument0);
    // if the json could not be parsed json_decode returns -1
    if( map == -1 ){ show_error("Json could not be read.", false);}
    // if it was a list, the list is found in "default
    var list = ds_map_find_value(map, "default");
    var len = ds_list_size(list);
    for (var i = 0, arr; i < len; i ++ ){
        arr[i] = list[|i];
    }
    ds_map_destroy(map);
    ds_list_destroy(list);
    return arr;
    
    usage would be jarray("[1,2,3,'a','b','c']")
     
    Last edited: Aug 10, 2016
  13. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    693
    While I really need to jump on the JSON bandwagon eventually, my way is still faster to type for me, plus JSON converts to data structures and not arrays.
     
  14. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    if you try the code snippet I put with my post you will see it returns an array. all you have to do is pass it a string like so:
    thearray = jarray("[1,2,3,4,5,'a','b','c',3,4,5,6,34,5,3,46,34,5,345,34,6,6]");

    if you need any real values in there you can also do that as well
    thearray = jarray("[1,2,3,"+string(score)+",values,blah]")


    this is not limited to a delimiter and it is not limited to 16 values. the code I pasted does get a ds from the json string but turns it into an array. It is far easier to use. for any array which has 16 or less values I would use Yal's version... any more I would use this jarray version... and when I am optimising my game I would refactor it out completely.
     
  15. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    693
    Oh, missed the array part. My bad. Of course, I wouldn't consider using the scripts I posted for performance heavy applications. I mostly just use them for once off, low impact areas. If I need arrays in high performance areas, I'd just code them manually. I wouldn't say yours is any easier to use, per say, simpler maybe, and yes, not limited to the delimiter (there's a bad pun in there somewhere). Just my preferred method is all.
     
    Abrexas and Salvakiya like this.
  16. Abrexas

    Abrexas Member

    Joined:
    Aug 10, 2016
    Posts:
    72
    I have learned a lot from this thread. Thank you all!
     
  17. Freddy Jones

    Freddy Jones Member

    Joined:
    Jul 3, 2016
    Posts:
    165
    I'd recommend not doing it at all, honestly. The time it will save you to write, won't save you the time it takes to debug and read. You'll also find that using these "string_to_array" functions will get pretty cumbersome when you want to insert a variable. If you're trying to find a specific index it might take you more time to look through the string instead of just looking for an index number that's already been pre-set. That's my two cents.

    Also, before using Salvakiya's code, there's a small problem with his usage of json_decode. It always returns a map, not a list, but can be used to get/parse lists nonetheless.
     
  18. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    it in fact does not always return a map. If the string starts with [ it returns a list... if its a { it returns a map. Let me know if I am wrong but you cant ds_list_destroy on a map. at least not in my tests.
     
  19. Freddy Jones

    Freddy Jones Member

    Joined:
    Jul 3, 2016
    Posts:
    165
    I would go with what the manual says. It says it will create a ds_map, and then for any lists found in the json it will make a list for on the inside. If you haven't made any lists or maps prior to calling the json function, it will seem that it returned a list, but in fact it will be chance that both the map and the list are of the same index (0 in this case).

    Therefor, it is best to stick with the example provided in the docs. If this is not true, then it is undocumented behaviour.
     
    elementbound and Salvakiya like this.
  20. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    I can confirm after further testing it does in fact return a map as you stated... silly me =P. one should use Freddy's version if they are to use it.
     
    Freddy Jones likes this.
  21. renex

    renex Member

    Joined:
    Jun 23, 2016
    Posts:
    506
    I should also add that the latest EA build removed the argument number limit, so an array building script is a very efficient approach.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice