MATLAB Answers

0

Putting the result from eval into a cell array

Asked by Nikolaos Zafirakis on 21 Jul 2019
Latest activity Edited by Stephen Cobeldick on 22 Jul 2019 at 4:13
Got the piece of code below. Basically, when I run it I get x_1 all the way to x_600 so i get 600 outputs I would like to put all of these into a cell array does anyone know how to do this cause I've failed at every attempt?
count=1;
for i=1:600
G = [ F(i)+1 , F(i+1) ];
a = unwrap(B);
eval(['x_' num2str(count) ' = a;']);
count=count+1;
end

  0 Comments

Sign in to comment.

2 Answers

Answer by Stephen Cobeldick on 21 Jul 2019
Edited by Stephen Cobeldick on 21 Jul 2019

N = 600;
C = cell(1,N); % preallocate.
for k = 1:N
G = [F(k)+1,F(k+1)]; % you never use G anywhere in your code...
C{K} = unwrap(B); % where is B defined?
end
"...I've failed at every attempt"
Because you picked a complex, slow, inefficient approach (using eval to create lots of variables), as opposed to simply using a cell array in the first place.

  9 Comments

So, if I run my unwrap function my measurements drift cause there are many. By using the loop and the eval I manage to run all the groups separately which I have not managed to do using some other code. The goal is to run the unwrap part through the code each individual batch and collect them at the output in the form of a cell array.
TADA
on 21 Jul 2019 at 22:50
This example shows how using eval is unnecessary
% create mock data
B = linspace(0, 10*pi(), 20)';
C = (1:numel(B))';
C(randi(18, 1, 3)) = 0; % randomly pop zeros in there to start new batches
% find all batches start and end points
[ D, E ] = find( C == 0 ); % D when zero occuers so batch starts
if D(1) ~= 1
D = [1; D]; % start from first index no matter what...
end
F = [D - 1; numel(B)]; % F when batch finishes
% if you need it for something...
count = numel(D);
% prepare cell array with cells for all detected batches
x=cell(1, count);
% iterate through all batches and extract the data into cell array "x"
for i=1:count
G = [ F(i)+1 , F(i+1) ]; % finding the begining and last point of each group
% do your calculation - this line of code is perfectly fine,
% although, the data could be stored directly into the cell array
% instead of the temporary variable "a"
a = unwrap(B(G(1):G(2),:)/2^15*pi)*2^15/pi;
% this will set the output of your calculation directly into the cell array
x{i} = a;
% this will needlessly declare a new variable called "x_i"
% where i is the current index
eval(['x_' num2str(i) ' = a;']); % Splits the outputs of the unwrap into seperate batches
end
celldisp(x);
x{1} =
0
1.6535
3.3069
4.9604
x{2} =
6.6139
8.2673
9.9208
x{3} =
11.5743
13.2278
14.8812
16.5347
18.1882
19.8416
21.4951
x{4} =
23.1486
24.8020
26.4555
28.1090
29.7625
31.4159
for i = 1:count
fprintf('x_%d: ', i);
fprintf('%d,', eval(['x_' num2str(i)]));
disp(newline);
end
x_1: 0,1.653470e+00,3.306940e+00,4.960409e+00,
x_2: 6.613879e+00,8.267349e+00,9.920819e+00,
x_3: 1.157429e+01,1.322776e+01,1.488123e+01,1.653470e+01,1.818817e+01,1.984164e+01,2.149511e+01,
x_4: 2.314858e+01,2.480205e+01,2.645552e+01,2.810899e+01,2.976246e+01,3.141593e+01,
TADA
on 21 Jul 2019 at 23:23
If you store data sets in arrays instead of indexed variables, you get only benefits:
  • Less code which is more readable:
x{i} = unwrap(B(G(1):G(2),:)/2^15*pi)*2^15/pi;
% instead of
count = count+1;
a = unwrap(B(G(1):G(2),:)/2^15*pi)*2^15/pi;
eval(['x_' num2str(count) ' = a;']);
  • No need to maintain a variable which counta your variables, simply use size(x) or numel(x)
  • No workspace spamming with 600 variables, theres only one cell array,matrix,table,etc. So you can actually see what variables you have in your workspace window.
  • Indexing performs way better than eval, several orders of magnitude better in fact
a = 1:100;
tic;
for i = 1:10000;
x{i} = a;
end;
toc;
Elapsed time 0.002012 seconds
tic;
for i = 1:10000;
eval(['x_' num2str(i) ' = a;']);
end;
toc;
Elapsed time is 3.508633 seconds

Sign in to comment.


Answer by TADA
on 21 Jul 2019

please please please don't use eval to access varriable names
eval is not built for that, however, for some reason the first thing that new programmers of any scripting language learn is to use eval which results in code which is confusing, performs poorly and is impossible to decypher and maintain
remember the rule, eval is evil.
if you remember that and only result to using eval when you realy have to (i.e. never!), your programing would improve dramatically.
the good practice in that case would be to use matrices to store your data instead of separate variables (i.e X1 X2 X3), or if they are different sizes a cell array
% same size:
x = zeros(3, 100);
x(1,:) = 1:100;
x(2,:) = 101:200;
x(3,:) = 201:300;
% different sizes:
x = {};
x{1} = 1:100;
x{2} = 1:1000;
x{3} = 1:10000;
Now, if that piece of code was given to you by some blackbox script written by someone else and it requires hundreds of hours of rewriting, I agree the correct way to handle this would be to use eval and export the data into a reasonable format:
% code you got from someone else
X1 = 1:100;
X2 = 1:1000;
X3 = 1:10000;
% code that accesses these variables and fixes that
c = {};
for i = 1:3
c{i} = eval(['X' num2str(i)]);
end

  0 Comments

Sign in to comment.