This post continues in the theme from my last post, where people routinely come to me on a topic. Today I want to distinguish between indexed assignment, where you can take advantage of scalar expansion, and assignment to several output arrays, often arising from a comma-separated list from cell or struct arrays.
Contents
First Explore Cell Arrays
Let's first explore some aspects of creating and populating the contents of a cell array. I first initialize 2 arrays, each of length 3.
a = {1 magic(3) 'hello'};
d = {'hi' 17 pi};Next I initialize another cell array to be the same as a.
c = a;
Now I attempt to change the contents of all the cells in c by assigning a new value that I want to show up in each cell.
try [c{:}] = 'aloha'; % error unless c is a scalar catch cellE disp(cellE.message) end
Too many output arguments.
As you can see, this didn't work. The reason is that I have 3 entities on the left-hand side, because c is a cell array of length 3 and I used the comma-separated list notion. MATLAB doesn't know how to make 3 separate arrays out of 1 by simple assignment.
I could use regular indexing on c to populate it however. In this case, the right-hand side has length 1 (a cell array with string contents) and the left-hand side is all of c. MATLAB can do scalar expansion for regular assignment into arrays which is why this works.
c(:) = {'ahola'}c =
'ahola' 'ahola' 'ahola'
How else might we populate all the cells in c? One way is to use the function deal. I prefer the line above; I think the code without deal is clearer and it doesn't have the extra function call overhead.
[c{:}] = deal('ola')c =
'ola' 'ola' 'ola'
If I have the values I want to store in the contents of c in another cell array, let's say d, I can again use deal but I don't have to. Compare the following 2 statements.
[c{:}] = deal(d{:})
[c{:}] = d{:}c =
'hi' [17] [3.1416]
c =
'hi' [17] [3.1416]
In the first of these, I expand the cell array on the right to a comma-separated list and pass it through the function deal which then distributes the outputs into c. In the second statement, I bypass the function call to deal with some relatively new (MATLAB 7) syntax.
Now Explore structs
Let's do a similar exercise with structs now.
s = struct('f',a);
s.fans =
1
ans =
8 1 6
3 5 7
4 9 2
ans =
hello
try [s.f] = 'bonjour'; % error unless s is a scalar catch structE disp(structE.message) end
Too many output arguments.
[s.f] = deal('hej');
s.fans = hej ans = hej ans = hej
[s.f] = d{:};
s.fans =
hi
ans =
17
ans =
3.1416
As you can see, I can bypass the function deal when assigning to a struct array in analogous way to cell array assignment.
References
Here are some prime references for getting more details on today's topic.
Why Do You Use deal?
I'd like to hear from you about situations where you feel using deal is your only option or you prefer it (perhaps readability?) to the no deal syntax. Let me know here.
Get
the MATLAB code
Published with MATLAB® 7.5



Say you have some struct containing names and phone numbers:
s = struct(’name’, {}, ‘phone’, {})
Then you can assign names to some fields in one line:
[s(1:3).name] = deal(’Loren’, ‘Doug’, ‘Steve’);
Without using deal, you would have to create a cell array and then assign:
c = {’Loren’, ‘Doug’, ‘Steve’};
[s(1:3).name] = c{:};
In this case the use of deal allows more compact code.
Markus
Loren,
I have always puzzled over the [c{:}] notation on the left hand side, but I think I may have had an epiphany. Is the reason for that notation that it is a shorthand form of the same method used for returning multiple outputs from a function? In short, is it simply the short form of writing:
[c{1}, c{2}, c{3}]? I guess what this question is really indicating is I’m not sure *exactly* what square brackets mean on the left hand side of an expression. On the right hand side, it’s not problem: “concatenate these inputs into a new array.” But that doesn’t really hold for the left hand side, I think. Can you give the english statement which left hand side brackets is equivalent to?
Thanks,
Dan
Loren,
I’m wondering why this works,
[b{1:3}]=deal(1,2,3);
[a{1:3}]=b{:};
while this doesn’t,
[a{:}]=1,2,3;
??? Too many output arguments.
As far as I know, 1,2,3 is a comma-separated list too –dare I say just as good as b{:}? So why shouldn’t the latter work just as the former does?
And actually, executing either
b{:}
or
1,2,3
gives the same output as one would expect,
ans =
1
ans =
2
ans =
3
What is it that I’m missing here?
-Omid
Loren,
This is an important topic. But, I’m stumbling over the first part of the example.
After your first example, the one that failed & generated an error, you say, “. . . because c is a cell array of length 3 and I used the comma-separated list notion.”
Where is the comma-separated list notion? ‘aloha’ doesn’t look like a comma-separated list to my eye. I can’t find this term defined in the MatLab documentation, yet there are several pages of documentation regarding comma-separated lists. This appears to be a key concept that is well understood by MatLab developers, but not me.
Although I can see that the failed syntax enclosed the target variable with the square brackets, I don’t understand the significance of the square brackets.
Further, when I compare the failed syntax with the one without the square brackets, that didn’t generate an error, they seem very similar.
Maybe the key question is, “How does the square brackets syntax interact with lists of comma-separated lists when the square bracket are used on the assignment side of the equals sign?”
Thanks.
I have used deal when creating lambda functions that generate more than one output:
@(x) deal(fn1(x), fn2(x))
Actually, for this purpose I quickly swapped to using this version of deal:
function varargout = mydeal(varargin)
varargout = varargin(1:max(1,nargout));
I wanted to create functions that behave like normal Matlab functions. That is, any outputs that aren’t asked for are silently discarded. Matlab’s deal throws an error if I do:
fn = @(x) deal(x, 2*x); y = fn(2);
So I use mydeal instead.
I try to avoid the deal function if at all possible. I have found that it can be much slower than using the commma seperated list notion.
Folks-
Thanks for all the great comments. I think Markus and Iain have both pointed out times when using deal (or a doctored version) make sense.
Dan, you are exactly right about what [] mean on the left side. It is the way MATLAB allows you to return more than one output and is not concatenation like it is when appearing on the right hand side. The comma-separated list c{1},c{2},c{3} is 3 outputs for MATLAB since each cell in a cell array is basically its own variable (though associated with all others in the same cell array). So [c{:}] builds up that list for you and allows you to return multiple left-hand sides from functions.
Omid-
MATLAB treats the physically appearance of , or ; or a newline as a line terminator. So 1,2,3 is 3 separate statements in MATLAB. However, the construct b{:} is treated as an entity unto itself, and allows concatenation into a regular or cell array when placed between [] or {}.
Oliver-
The comma-separated list referred to in that statement was for the left-hand side [c{:}] and not to ‘aloha’ which is a simple string value. The [] on the left allows me to assemble a list of output variables. And the c{:} in between builds the list c{1},c{2},c{3}.
–Loren
Hello, Loren and everyone.
Deal is for sure a powerful tool, but the most frequent way I use deal is to swap values:
[b,a] = deal(a,b);
Ok, so:
—
%what if I have a vector of integers:
num_vec = [1 7 3 5 9];
%and I structure array with same number of fields:
[mystruct(1:5).a] = deal(’a',’b',’c',’d',’e');
%I want to assign num_vec as the the ‘b’ field of mystruct.
%The following does not work:
mystruct = setfield(mystruct,{1:5},’b',num_vec)
%and deal only works with cells:
[mystruct.b] = deal(num_vec);
—
There should be a one line way to assign a scalar array to
a field of a structure array. Please tell me how to do
this. Going between comma-separated lists, cells, and arrays is unnecessariy frustrating, and is one of my only major complaints about MATLAB.
Daniel-
Convert your numbers into a cell array:
mycell = num2cell(num_vec);
Then you can do this:
[mystruct.b] = mycell{:}
The point is you have to have your RHS in cells to distribute them easily.
–Loren
I have an observation about the performance of the expression mycell{:} - its running time is quadratic in the number of elements, which makes it quite slow for large number of elements. This also seems to affect the [s.field] syntax for structs.
I have a cell array where each cell contains a numeric vector. What I’d like to do is concatenate certain subsets of the whole cell array, like this: cat(1, c{:}). However, look at the running times of c{:} with different number of elements (in 2008b) and notice how each increase by power of 10 increases the running time by about a factor of 100:
>> for ii = [100 1000 10000 100000], clear c; c(1:ii)={1}; tic; c{:}; toc; end
Elapsed time is 0.000056 seconds.
Elapsed time is 0.003090 seconds.
Elapsed time is 0.304656 seconds.
Elapsed time is 45.346996 seconds.
It would be interesting to know why this is happening. This, of course, also affects cell2mat - the last two lines of code from that file are
% Finally, concatenate the final rows of cells into a matrix
m = cat(1,c{:});
Do you have any suggestions on how to achieve cat(1, c{:}) but with a reasonable running time?
Thanks.
Tom
Tom-
Your test case is almost a worst-case scenario in that you are assigning all the cell values to the same array. In the guts of MATLAB, these are all pointing to the same memory which slows the {:} operation down more than if the values were distinct. In either case however there is quadratic performance as you observe (and the development team is aware of this). Alas, I do not have a timeframe for changing this runtime characteristic.
The way to work around it is with a for loop, which should give linear speed with pre-allocation. Not as pretty, but hopefully should help you out for now.
–loren
Loren,
I also contacted support who explained this in a little more detail.
In reality, my data will not be shared in this way, so this becomes a non-issue. Once I created a cell array with no shared cells, I got the performance characteristics I was expecting.
Many thanks,
Tom
Loren,
Question is if deal or better way to create structure array in the situation below? I tried but hadn’t succeeded.
I have Stateflow.Data in a cell,
>> dparam
dparam =
[1×1 Stateflow.Data] [2×1 Stateflow.Data]
Then I create a structure array x by
>>clear x; x=dparam{1}; x(2:3)=dparam{2};
Now I can perform
>> get(x,’Name’)
ans =
‘gain’
‘gain’
‘gain1′
Wei-
There does not seem to be any particular advantage to using deal with your data structure.
–Loren
Loren,
I was trying to avoid a loop. Thank you for answering. Could deal or else help to eliminate temp variable ‘name’ below?
>> name = get(da,’Name’);
>> sfData = struct(’Name’,cell(3,1));
>> [sfData(:).Name]=name{:};
Wei-
I don’t know where you are talking about using a loop. It’s hard to tell what your final outcome is supposed to be. For now, I can’t tell if you can avoid the temporary variable, but is it really hurting anything?
–Loren
Loren,
The loop is referring #14 where I have to index through cell array dparam to produce struct array x.
In #16 array x is da
>> da
da =
Stateflow.Data: 1-by-3
From which I want to extract info to create a struct array sfData. Now I’m thinking to avoid temp ‘name’.