Using Lua tables as 2-dimensional arrays - arrays

I'm a beginner Lua user, I attempt to create something in Lua by using Love2D libraries.
In the loading function I create a table and upload it with elements (which are numbers) for use it later as a multidimensional array.
function love.load()
Maximum_X = 32
Maximum_Y = 16
Start_X = 64
Start_Y = 32
MapTable = {} -- empty table
for i=1,Maximum_X*Maximum_Y do -- uploading table
table.insert(MapTable, 2)
end
end
Then I make a function that takes changes in the table. Because I'm just experimenting with tables, there's only one changed value. At least, I thought.
function KatamoriGen()
MapTable[4] = 3
end
function love.update(dt)
KatamoriGen()
end
After that, I print the elements of the table in a matrix with 32 coloumns and 16 rows. I see here that not only the 4th element of 1st row is changed, but also the 2nd element of 2nd row and 1st element of 4th row becomes 3.
It obviously means that Table[posX*posY] doesn't work neither since the result of the multiplication is a number like 4 and the operation would change every elements where
X coordinate + Y coordinate = posX*posY
is true. In the example code, the right side of this equation was 4.
A small question: why is it happening?
The main question is: how can I identify elements of MapTable exactly? How can I implement X and Y dimensions to Lua tables? to use them as two-dimensional arrays? Maybe table of tables?
EDIT: this is the drawing function:
function love.draw()
for j=1,16 do
for i=1,32 do
love.graphics.draw(Tileset[MapTable[j*Maximum_X + i]], Start_X + 32*(i-1), Start_Y + 32*(j-1))
end
end
end
Now it's clear for me that this is wrong and the right rule is MapTable[j*Maximum_X + i] but I get an error for it: "expected parameter type: expected userdata"

You can also use multi-dim tables. Something like:
local MapTable = {}
local Maximum_X, Maximum_Y = 32, 16
local Start_X, Start_Y = 64, 32
function love.load()
for y = 1,Maximum_Y do
local row = {}
for x = 1,Maximum_X do
table.insert(row,2)
end
table.insert(MapTable,row)
end
end
function love.draw()
for y,row in ipairs(MapTable) do
for x,idx in ipairs(row) do
love.graphics.draw(Tileset[idx], Start_X + 32*(x-1), Start_Y + 32*(y-1))
end
end
end

As Alex shows it, the problem was not with the way how table works, but rather that I displayed the numbers on a wrong way. Tables can be used as one-dimensional arrays, and everything fine then.
Even though it's not a solution for using them as 2-dimensional array, the main problem is solved.

Related

Filling a row and columns of a ndarray with a loop

I'm starting with Python and I have a basic question with "for" loop
I have two array which contains a values of a same variables:
A = data_lac[:,0]
In the first array, I have values of area and in the second on, values of mean depth.
I would like to find a way to automatize my calculation with different value of a parameter. The equation is the following one:
g= (np.sqrt(A/pi))/n
Here I can calculte my "g" for each row. Now I want to have a loop with differents values of "n". I did this:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i] = (np.sqrt(A[i]/pi))/n
i += 1
break
In this case, I just have one column with the calculation for n = 2 but not the following one. I tried to add a second dimension to my array but I have an error message saying that I have too many indices for array.
In other, I would like this array:
g[len(A),5]
g has 5 columns each one calculating with a different "n"
Any tips would be very helpful,
Thanks
Update of the code:
data_lac=np.zeros((106,7))
data_lac[:,0:2]=np.loadtxt("/home...", delimiter=';', skiprows=1, usecols=(0,1))
data_lac[:,1]=data_lac[:,1]*0.001
#Initialisation
A = data_lac[:,0]
#example for A with 4 elements
A=[2.1, 32.0, 4.6, 25]
g = np.zeros((len(A),))
I believe you share the indexes within both loops. You were increasing the i (index for the upper while loop) inside the inner for loop (which index with n).
I guess you have A (1 dim array) and you want to produce G (2 dim array) with size of (Len(A, 5))
I am not sure I'm fully understand your require output but I believe you want something like:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i][n-2] = (np.sqrt(A[i]/pi))/n # n-2 is to get first index as 0 and last as 4
i += 1 # notice the increace of the i is for the upper while loop
break
Important - remember that in python indentation means a lot -> so make sure the i +=1 is under the while scope and not indent to be inside the for loop
Notice - G definition should be as:
g = np.zeros((len(A),4), dtype=float)
The way you define it (without the 4) cause it to be 1 dim array and not 2-dim

How To Loop Array with Two Samples in Matlab?

I would like to take two constants from the array constants at a time because I do not want to go one by one these constants through because it is time consuming; instead, I compare the changes what they cause and only react if there is a big change between the effects of two constants.
I am looping one sample constant in the array constants at a time in Matlab 2016a
constants=[45 90 180 360 720 1440 2880 5760]';
for constant=constants
...
end
However, I would like to take two constants at a time by one loop, like pseudocode
for constant1,constant2=constants
...
end
How can you take two constant(s) from constants in one for loop of Matlab?
Something like this?
for index = 1:length(constants) - 1
c1 = constants(index);
c2 = constants(index + 1);
end
Another option is to define a function that pairs each element with the next element in the array -
function result = pairAdjacent(array)
result = [array(1:end-1) ; array(2:end)];
end
and then do
for constant = pairAdjacent(constants)
c1 = constant(1);
c2 = constant(2);
end
Recall that when you use the notation
for elem = array
// Now elem is a single column from array
end
the variable elem is assigned successively to each of the columns of array, so your array constants needs to be a 1xN array for this to work correctly.

How to name variables in a data array using a for loop

I have an array within an array and I am trying to name the variables using a for loop as there are a lot of variables. When I use the following simple code Time1 = dataCOMB{1,1}{1,1}(1:1024, 1); it opens the first cell in an array and proceeds to open the first cell in the following array and finally defines all the values in column 1 rows 1 to 1024 as Time1. However I have 38 of these different sets of data and when I apply the following code:
for t = 1:38
for aa = 1:38
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
end
end
I get an error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in Load_Files_working (line 39)
Time(t) = dataCOMB{1,1}{1,aa}(1:1024, 1);
Basically I am trying to get matlab to call the first column in each data set Time1, Time2, etc.
The problem:
1)You'd want to extract in a cell row...
2) ...the first 1024 numbers in the 1st column...
3) ...from each of the first 38 cells of a cell array.
The plan:
1) If one wants to get info from each element of a cell array (that is, an array accessed via {} indexing), one may use cellfun. Calling cellfun(some_function, a_cell_array) will aggregate the results of some_function(a_cell_array{k}) for all possible k subscripts. If the results are heterogeneous (i.e. not having the same type and size), one may use the cell_fun(..., 'UniformOutput', false) option to put them in an output cell array (cell arrays are good at grouping together heterogeneous data).
2) To extract the first 1024 numbers from the first column of an numeric array x one may use this anonymous function: #(x) x(1:1024,1). The x argument will com from each element of a cell array, and our anonymous function will play the role of some_function in the step above.
3) Now we need to specify a_cell_array, i.e. the cell array that contains the first 38 cells of the target. That would be, simply dataCOMB{1,1}(1,1:38).
The solution:
This one-liner implements the plan:
Time = cellfun(#(x) x(1:1024,1), dataCOMB{1,1}(1,1:38), 'UniformOutput', false);
Then you can access your data as in this example:
this_time = Time{3};
Your error is with Time(t). That's not how you create a new variable in matlab. To do exactly what you want (ie, create variables names Time1, Time2, etc...you'll need to use the eval function:
for aa = 1:38
eval(['Time' num2str(aa) '= dataCOMB{1,1}{1,aa}(1:1024,1);']);
end
Many people do not like recommending the eval function. Others wouldn't recommend moving all of your data out of a data structure and into their own independently-named variables. So, to address these two criticisms, a better alternative might be to pull your data out of your complicated data structure and to put it into a simpler array:
Time_Array = zeros(1024,38);
for aa = 1:38
Time_Array(:,aa) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
Or, if you don't like that because you really like the names Time1, Time2, etc, you could create them as fields to a data structure:
Time_Data = [];
for aa = 1:38
fieldname = ['Time' num2str(aa)];
Time_Data.(fieldname) = dataCOMB{1,1}{1,aa}(1:1024,1);
end
And, in response to a comment below by the original post, this method can be extended to further unpack the data:
Time_Data = [];
count = 0;
for z = 1:2;
for aa = 1:38
count = count+1;
fieldname = ['Time' num2str(count)];
Time_Data.(fieldname) = dataCOMB{1,z}{1,aa}(1:1024,1);
end
end

Dynamically creating and naming an array

Consider the following code snippet
for i = 1:100
Yi= x(i:i + 3); % i in Yi is not an index but subscript,
% x is some array having sufficient values
i = i + 3
end
Basically I want that each time the for loop runs the subscript changes from 1 to 2, 3, ..., 100. SO in effect after 100 iterations I will be having 100 arrays, starting with Y1 to Y100.
What could be the simplest way to implement this in MATLAB?
UPDATE
This is to be run 15 times
Y1 = 64;
fft_x = 2 * abs(Y1(5));
For simplicity I have taken constant inputs.
Now I am trying to use cell based on Marc's answer:
Y1 = cell(15,1);
fft_x = cell(15,1);
for i = 1:15
Y1{i,1} = 64;
fft_x{i,1} = 2 * abs(Y1(5));
end
I think I need to do some changes in abs(). Please suggest.
It is impossible to make variably-named variables in matlab. The common solution is to use a cell array for Y:
Y=cell(100,1);
for i =1:100
Y{i,1}= x(i:i+3);
i=i+3;
end
Note that the line i=i+3 inside the for-loop has no effect. You can just remove it.
Y=cell(100,1);
for i =1:100
Y{i,1}= x(i:i+3);
end
It is possible to make variably-named variables in matlab. If you really want this do something like this:
for i = 1:4:100
eval(['Y', num2str((i+3)/4), '=x(i:i+3);']);
end
How you organize your indexing depends on what you plan to do with x of course...
Yes, you can dynamically name variables. However, it's almost never a good idea and there are much better/safer/faster alternatives, e.g. cell arrays as demonstrated by #Marc Claesen.
Look at the assignin function (and the related eval). You could do what asked for with:
for i = 1:100
assignin('caller',['Y' int2str(i)],rand(1,i))
end
Another related function is genvarname. Don't use these unless you really need them.

Saving return values of function returning multiple variables in Matlab

I have never used matlab before so excuse this very basic question.
Basically I have a function that returns multiple variables, defined like so:
function [a, b, c]=somefunction(x, y, z)
I know I can get the return values as follows:
[a,b,c] = somefunction(1,2,3);
Now what I would like to do instead is save multiple runs of somefunction into an array and then retrieve them later. I tried:
results = [];
results = [results somefunction(1,2,3)];
results = [results somefunction(4,5,6)];
And then I tried accessing the individual runs as:
% access second run, i.e. somefunction(1,2,3) ?
a = results(2, 1);
b = results(2, 2);
c = results(2, 3);
but this tells me that the index is out of bound because size(results) = [1,99654] (99654 is the number of results I need to save). So it does not appear to be an array? Sorry for this basic question, again I have never used matlab.
When you combine arrays with [ ... ], you're concatenating them, creating one long flat array. For example, if call 1 returns 3 elements, call 2 returns 8 elements, and call 3 returns 4 elements, you'll end up with a 14-long array, and no way of knowing which elements came from which function call.
If you want to keep the results from each run separate, you can stash them in a cell array. You still need a comma-separated list on the LHS to get all the multiple argouts. The {}-indexing syntax, as opposed to (), "pops" contents in and out of cell elements.
Let's store the results in a k-by-n array named x, where the function returns n outputs and we'll call it k times.
x = cell(2, 3); % cell(k, n)
% Make calls
[x{1,1}, x{1,2}, x{1,3}] = somefunction(1,2,3);
[x{2,1}, x{2,2}, x{2,3}] = somefunction(4,5,6);
% Now, the results of the ni-th argout of the ki-th call are in x{ki,ni}
% E.g. here is the 3rd argout from the second call
x{2,3}
You could also store the argouts in separate variables, which may be more readable. In this case, each will be a k-long vector
[a,b,c] = deal(cell(1,2)); % cell(1,k)
[a{1}, b{1}, c{1}] = somefunction(1,2,3);
[a{2}, b{2}, c{2}] = somefunction(1,2,3);
And of course this generalizes to loops, if your somefunction inputs are amenable to that.
[a,b,c] = deal(cell(1,nIterations));
for k = 1:nIterations
[a{k}, b{k}, c{k}] = somefunction(1,2,3);
end
Details are in the doco at http://www.mathworks.com/help/matlab/cell-arrays.html or doc cell.
(Side note: that results(1, 2) in your post ought to succeed for an array of size [1,99654]. Sure you didn't do results(2, 1)?)

Resources