Setting up Arrays in one line - arrays

Im trying to set up an array with six integer values and one string in one line. I know how to do this one line at a time but cant figure out how to set it up in GameMaker.
array[0] = 10;
array[1] = 1;
array[2] = 5;
array[3] = 12;
array[4] = 12;
array[5] = 3;
array[6] = spr_sprite;
But ideally id like to avoid having multiple lines of code if i can. So how do i set it up in one line?

You can use that extention from the Marketplace (script array_create). Or create it yourself:
/// array_create(value1, value2, ...)
var res;
var n = argument_count - 1;
while (n-- >= 0)
{
res[n] = argument[n];
}
return res;
Old verisons of GMS may use 16 arguments maximum, but some time ago this limit was removed and now you can use about 700 arguments (actually I don't remember exact value and I guess this may differ on different hardware).
On GMS2 you can initialize arrays using the syntax
var a = [1, 2, 3, 4];

Related

How can you initialize an entire array at once in GML?

I want to initialize an entire array at once but I can't find any examles of this being done anywhere.
I want to do something like this:
int a [][] = {{0,1,0},
{0,1,1},
{2,1,0}};
Unfortunately GML is not like many other languages in the sense that GML does not have single line array initialization. You can easily write a script to accomplish this, but the GML docs use this method to initialize arrays. The example they gave initializes a 10 record array (0-9) with zeros.
var i;
i = 9;
repeat(10)
{
array[i] = 0;
i -= 1;
}
If you want different values for every record then you have to manually type every position. This is the example the docs gave.
count = 3;
array[count] = "you?"
count -= 1;
array[count] = "are "
count -= 1;
array[count] = "How "
count -= 1;
array[count] = "Hello!"
count -= 1;
In regards to a script: Here is a simple one for 1D arrays. Used as var myArray = array(record 1, record 2, 3, 4, ...)
///array(*args);
var arr;
for (var i=0;i<argument_count;i+=1)
{
arr[i] = argument[i];
}
return arr;
If you are using a current version of GameMaker, there's array literal syntax in form of [...items] (documentation). So you can do
a = [[0,1,0],
[0,1,1],
[2,1,1]];
and that'll work fine.
The only thing to note that this'll produce an array of arrays (which is how arrays work in most languages) rather than GML-specific legacy 2d array, so you'd need to use a pair of [index] accessors rather than [index1, index2].

Is it possible to average across array of structure sub-fields in Matlab without looping?

I have a function that processes an individual data set, and stores the outcome metrics in a data set like so:
trial_data.output_metric_a.value_1 = 2;
...
trial_1 = trial_data;
This function is applied to a number of different trials and are stored as an array struct:
% trial_1.output_metric_a.value_1 = 4
% trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
Is it possible to get averages and standard deviations of the sub-field values
without looping through the data structure?
Ideally:
mean_trials = mean(trials)
mean_trials.output_metric_a.value_1 == 3 % true
A possible loop implementation to solve this could be (obviously this leaves much to be desired):
output_metric_a_value_1 = [];
...
for i:length(trials)
output_metric_a_value_1(end+1) = trials(i).output_metric_a.value_1;
... % For each output metric and value
end
mean_trials.output_metric_a.value_1 = mean(output_metric_a_value_1);
You can convert the main struct to cell, then operate on the contents:
% your data base:
trial_1.output_metric_a.value_1 = 4
trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
% convert to cell:
Ctrials=struct2cell(trials);
Atrials=[Ctrials{:}];
meanTrials=mean([Atrials.value_1])
meanTrials=
3
Special Solution (not-nested struct > array)
As already mentioned, aiming for just one level of struct fields (not nested) one can basically go for a one-liner:
sarr_mean = cellfun(#(fn) mean([sarr.(fn)]), fieldnames(sarr))
Remark: In the not-nested case, there is not really a need to assign the resulting array back to a struct. If required, you can do it analogously to the full solution below.
Full Solution (nested struct > nested struct)
However, with arbitrarily nested arrays, I suggest to use a function such as the following:
% f... function handle
% s... nested struct array
function sarr_res = nestedSarrFun(f, s)
if isstruct(s)
% get fieldnames:
fns = fieldnames(s);
% get content:
con = cellfun(#(fn) nestedSarrFun(f, [s.(fn)]), ...
fns, 'UniformOutput', false);
% create return struct
fnsCon = reshape([fns(:), con(:)]', [1,2*numel(fns)]);
sarr_res = struct(fnsCon{:});
else
sarr_res = f(s);
end
end
Usage Example
Define example struct array and apply mean via nestedSarrFun:
% define example struct array "sarr" with fields
% .foo.bar1
% .bar2
% .dings
sarr = struct();
sarr(1).foo.bar1 = 2;
sarr(1).foo.bar2 = 7;
sarr(1).dings = 1;
sarr(2).foo.bar1 = 5;
sarr(2).foo.bar2 = 5;
sarr(2).dings = 2;
% apply mean to all nested fields:
sarr_mean = nestedSarrFun(#mean, sarr);
Example Result:
sarr_mean.foo.bar1 = 3.5
sarr_mean.foo.bar2 = 6
sarr_mean.dings = 1.5
In Matlab2017 (I am not sure about older versions), an array of structs can return an array of the field of its structs like so:
struct1.x = 1;
struct2.x = 2;
% array of 2 structs:
struct_array = [struct1, struct2];
% array of field x of each struct:
[struct_array.x]
which returns
ans =
1 2
In your case, the data is not in a field of your struct, but in a subfield output_metric_a. Therefore, you first need to this twice:
trial1.output_metric_a.value_1 = 1;
trial2.output_metric_a.value_1 = 2;
trials = [trial1, trial2];
output_metric_a_array = [trials.output_metric_a];
value_1_array = [output_metric_a_array.value_1];
mean_of_value_1 = mean(value_1_array)
which returns
mean_of_value_1 =
1.5000

How to return the leaves of a struct as vector in Matlab?

Often I need to access the leaves of data in a structured array for calculations.
How is this best done in Matlab 2017b?
% Minimal working example:
egg(1).weight = 30;
egg(2).weight = 33;
egg(3).weight = 34;
someeggs = mean([egg.weight]) % works fine
apple(1).properties.weight = 300;
apple(2).properties.weight = 330;
apple(3).properties.weight = 340;
someapples = mean([apple.properties.weight]) %fails
weights = [apple.properties.weight] %fails too
% Expected one output from a curly brace or dot indexing expression,
% but there were 3 results.
If only the top level is a non-scalar structure array, and every entry below is a scalar structure, you can collect the leaves with a call to arrayfun, then do your calculation on the returned vector:
>> weights = arrayfun(#(s) s.properties.weight, apple) % To get the vector
weights =
300 330 340
>> someapples = mean(arrayfun(#(s) s.properties.weight, apple))
someapples =
323.3333
The reason [apple.properties.weight] fails is because dot indexing returns a comma-separated list of structures for apple.properties. You would need to collect this list into a new structure array, then apply dot indexing to that for the next field weight.
You can collect properties into a temporary structure array, and then use it as normal:
apple_properties = [apple.properties];
someapples = mean([apple_properties.weight]) %works
This wouldn't work if you had even more nested levels. Perhaps something like this:
apple(1).properties.imperial.weight = 10;
apple(2).properties.imperial.weight = 15;
apple(3).properties.imperial.weight = 18;
apple(1).properties.metric.weight = 4;
apple(2).properties.metric.weight = 7;
apple(3).properties.metric.weight = 8;
Not that I would advise such a structure, but it works as a toy example. In that case you could, do the same as the previous in two steps... or you could use arrayfun.
weights = arrayfun(#(x) x.properties.metric.weight, apple);
mean(weights)

determine if array contains specific integer in octave

I have an array which looks like
test = {1,2,3};
I want to determine if an integer belongs in the array. I tried using ismember() and any() but they both return this:
binary operator '==' not implemented for 'cell' by 'scalar' operations
How will I do this? Thanks in advance
If you want to check if an integer exists in a matrix:
test = [1, 2, 3];
any (test == 2)
ans = 1
But in your question you use a cell array. In this case I would first convert it to a matrix, then do the same:
b = {1,2,3};
any (cell2mat (b) == 2)
ans = 1
You're asking about checking if an array has a given integer but you're using a cell. They're quite different.
If you want to stick to cells you can iterate over it like so
test = {1, 2, 3};
number = 2;
hasNumber = false;
for i = 1:size(test,2)
if(test{i} == number)
hasNumber = true;
break;
end
end
For arrays, on the other hand, you could do just this, for example
test = [1, 2, 3];
number = 2;
hasNumber = ~isempty(test(test == number));

Efficently move multiple items in array from oldlocation to new location

For example suppose we have:
a = [0,1,2,3,4];
And suppose we want to move the element 1 and 2 after 4 so a = [0,3,4,1,2]. What we want to move from and to is given by the following data:
oldLocation = [1,2] #move item a[1] and a[2]
newLocation = [3,4] #move to a[3] and a[4]
Now notice the newLocation is relative to the original array a. So I can't just move one by one from old to new location, since the array would be modified. I need some special handling.
Any thoughts? Currently I'm making copy of array a and copying everything but the moved model. Then inserting the moved model at the specified position. Then setting a to the newly adjust array.
Language doesnt really matter, but I'm using javascript.
int [] swap(int[] a, int[] oldl, int[] newl) {
int len = oldl.length; // or newl.length
for (int i = 0; i < len; i++) {
int oldi = oldl[i];
int newi = newl[i];
int temp = a[oldi]; // swap both
a[oldi] = a[newi];
a[newi] = temp;
}
return a;
}
Please try to put effort & solve easier stuffs by yourself.

Resources