3

I currently have a function which I am batch running. It outputs its results to a cell array. I would like to export each of the outputs from the cell array to their own variable.

As such I have a variable id which records the ID of each layer. This process is possible manually as follows:

>> output = 

[300x300x2 double]    [300x300x2 double]    [300x300x2 double]

>> [a1,a2,a3]=deal(output{:});

Where the number after a represents the ID. Is it possible to automate this command, so that the prefix (in this case: a) can be set by the user and the id filled in automatically? As in, I could have variables set as below, and use these in the deal command to name my new variables?

>> id =

 1     2     3

>> prefix =

a

Any ideas? Thanks.

1
  • I have managed to solve as follows: prefix= 'r'; id = [1:1:3] for i=1:length(id) s = ['[' layer int2str(id) '] = deal(cell{i});']; eval(s); end Commented Nov 3, 2011 at 15:49

4 Answers 4

2

You can construct your own custom expression as a string and then evaluate it with eval() (or evalin() if it's in a function and you want to return the output to your workspace).

function deal_output(output, id, prefix)

id     = id(:);
vars   = strcat(prefix, cellstr(num2str(id)))';
myexpr = ['[', sprintf('%s,', vars{1:end-1}), vars{end}, '] = deal(output{:})'];

evalin('caller', myexpr)
>> output = num2cell(1:3);
>> id     = 1:3;
>> prefix = 'a';
>> deal_output(output, id, prefix)

a1 =

     4


a2 =

     5


a3 =

     6

Also check out the join.m file on FileExchange for avoiding the ugly sprintf.

Sign up to request clarification or add additional context in comments.

1 Comment

Is there anyway this could be turned into a function?
2

Perhaps something like:

function dealinto(prefix, cellarray)
% DEALINTO
% USAGE
%   dealinto('a', {'one', 'two', 'three'})
% Causes these variables to be set in the base workspace:
% a1: 'one'
% a2: 'two'
% a3: 'three'    
for i=1:numel(cellarray)
    assignin('base', [prefix num2str(i)], cellarray{i});
end

If you replace 'base' with 'caller' in the above, the variables will be written into the calling function's workspace. I don't recommend doing this, though, for the same reason that I would not recommend calling LOAD with no output arguments inside a function: arbitrarily writing into a running function's workspace isn't very safe.

If you need something like this for use inside of functions but don't want it just writing variables willy nilly, you could do the same thing that LOAD does, which is to give you a structure whose fields are the variables you would otherwise produce.

3 Comments

I suggest replacing 'base' with 'caller' in the assignin statement, so that the function can be used from within a function as well.
@Jonas, I mentioned that, but I don't recommend it. I almost made ws an argument to the function, but I think the only sensible use case for this function is for interactive use. Sometimes people need to do weird things, though, so whatever works.
[name, task, mode] = deal_into(regexp(file, '-', 'split') doesn't seem weird. Python, for example, allows you to do something like that without any extra effort, and its very convenient, e.g. parsed = parse(filename) vs name, task, mode = parse(file) would both work provided the function returns a tuple of the right arity.
0

Do you really have to output them as completely separate variables? It would be much more efficient to use dynamic field names in a structure as this would avoid the use of the eval() statement. See the MATLAB blogs for avoiding eval()

In this case

m = length(output);
[a(1:m).data] = deal(output{:});

This will return a structure array, the length calculation is added so it'll work for different sizes of the output cell array.

Each array can be accessed individually with an id number.

a(1).data
a(2).data
a(3).data

Comments

0

I can't seem to add a comment so I'm adding an answer in the form of a question ^_^

Is it not better to pre-create the list of names and check them in the caller workspace using genvarname ?

Names = cell(1,numel(data))
for idx = 1:numel(data)
 Names{idx} = [Prefix, num2str(idx)]
end
Names = genvarname(Names,who)
dealinto(Names, data)

would prevent any invalid names from being create in the existing work space, then dealto would need to be modified as

function dealinto(Names, Values)
for idx = 1:length(Names)
 assignin('caller', Names(idx), Values(idx))
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.