I have a bunch of char arrays within a cell array that actually represents the declaration of MATLAB structs. Something like this:
tmp{1} = 'testData.input = [1;2;3;4;5]'
tmp{2} = 'testData.output = [2;4;6;8;10]'
I need to execute these "commands" and eventually create the respective struct. I am using the eval
function within a for-loop and it works.
numEntries = numel(tmp);
for i = 1 : numEntries
eval(tmp{i});
end
However, this is painfully slow. I should mention that the real char arrays are very large, effectively containing more than 3,000 numbers. Also, the tmp
cell array itself contains some 25,000 cells.
Is there a way to improve performance given that I can't change the input data, i.e. tmp
is simply given from an external source?
I cannot test if it is significantly faster with only the 2 lines you gave as an example but I would expect this method to be faster when the number of elements of tmp
grows.
The idea is to write all the assignment instructions contained into tmp
into a text file (an .m
file actually), then simply execute the .m
file. For large number of lines I would expect that to be way faster than having to invoque eval
repeatedly in a loop.
So here goes, this works fine with your example tmp
, you end up with the structure testData
in your workspace.
%% Create an '.m' file containing all the assignment instructions from the cell array
tmpFile = 'tmpFile2execute.m' ;
fidw = fopen( tmpFile , 'w' ) ;
fprintf(fidw,'%% Auto generated file\n'); % or any other header line you want, or none...
for i = 1 : numel(tmp) ;
fprintf(fidw,'%s ;\n',tmp{i});
end
fclose(fidw) ;
% (optional) only to keep workspace tidy
clear i fidw tmpFile tmp
%% Execute the file
tmpFile2execute ;
Expanding on the idea you could make it a function
instead of a script
, where you could add some post processing and return the result in a variable instead of directly in the workspace but you have to see if the base idea brings any speed improvment first.
cellfun(@eval,tmp);
will somewhat improve the performance over a loop. Otherwise, you may have to write your own parser (which may be faster if a limited type of input is expected, e.g. only assignment like structure.some_field.some_other_subfield = [some_array]; ).
Please note that eval
is a risky function to use (if Mr. Mischief writes in the input data something like !rm -Rf /
, !del *.*
or rmdir(matlabroot,'s')
you may end-up with a big mess evaluating those strings)