How to operate on comma separated lists ?

86 views (last 30 days)
How do I work with comma separated lists ? Below I have 3 structures with member MeanIntensity. I want to concatenate all MeanIntensity into another structure member RGB. How can I do that ?
r_data = regionprops(label, image(:,:,1), 'PixelValues', 'MeanIntensity');
g_data = regionprops(label, image(:,:,2), 'PixelValues', 'MeanIntensity');
b_data = regionprops(label, image(:,:,3), 'PixelValues', 'MeanIntensity');
[regions(:).RGB] = [r_data(:).MeanIntensity, g_data(:).MeanIntensity, b_data(:).MeanIntensity)];
I went to concatenate the data to get a 100 x 3 matrix
rgb = [vertcat(r_data(:).MeanIntensity), vertcat(g_data.MeanIntensity), vertcat(b_data.MeanIntensity)]
Now my task is to figure out how to push this into regions(:).RGB. Why does this not work ?
[regions(:).MeanIntensity] = deal([rgb(:,1), rgb(:,2), rgb(:,3)]);
This doesnt work either
[regions(:).MeanIntensity] = [rgb(:,1), rgb(:,2), rgb(:,3)];
how ?
  1 Comment
Stephen23
Stephen23 on 17 Jan 2017
Edited: Stephen23 on 30 Jan 2018
You should be able to assign to multiple structure elements. This works without error:
S(1).A = 1;
S(1).B = 2;
S(2).A = 3;
S(2).B = 4;
[S.Z] = deal(S.A)

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 17 Jan 2017
Edited: Stephen23 on 24 Dec 2021
Introduction: Comma-separated lists are really very simple. You use them all the time. Here is one:
a,b,c,d
That is a comma-separated list containing four variables, the variables a, b, c, and d. Every time you write a list of variables separated by commas then you are writing a comma-separated list. Most commonly you would write a comma-separated list as inputs when calling a function or operator:
fun(a,b,c,d)
or as the outputs:
[a,b,c,d] = fun();
It is very important to understand that in general a comma-separated list is NOT one variable! However sometimes it is useful to create a comma-separated list from one variable (or define one variable from a comma-separated list), and MATLAB has several ways of doing this:
struct_array.field % all elements
struct_array(idx).field % selected elements
cell_array{:} % all elements
cell_array{idx} % selected elements
3) from a string array (undocumented, but works fine):
string_array{:} % all elements
string_array{idx} % selected elements
Note that these are still exactly equivalent to what I wrote at the top: they will generate this comma-separated list:
variable1, variable2, variable3, .. , variableN
and they will generate as many variables in that list as the structure or cell or string array has elements (or that are selected using indexing). A comma-separated list of one is equivalent to one single variable, but otherwise there can be zero, two, three, four, or more variables. Here is an example showing that a comma-separated list generated from a cell array is the same as a comma-separated list written explicitly:
>> C = {1,0,Inf};
>> C{:}
ans =
1
ans =
0
ans =
Inf
>> 1,0,Inf
ans =
1
ans =
0
ans =
Inf
Function Inputs: Remember that every time you call a function with multiple input arguments you are using a comma-separated list:
fun(a,b,c,..)
and this is exactly why they are useful: because you can specify the arguments for a function or operator without knowing anything about the arguments (even how many there are). Using my example cell array from above:
>> vertcat(C{:})
ans =
1
0
Inf
which, as we should know by now, is exactly equivalent to writing the same comma-separated list directly into the function call:
>> vertcat(1,0,Inf)
ans =
1
0
Inf
How can we use this? Commonly these are used to generate vectors of values from a structure or cell array, e.g. to concatenate the names which are in the output structure of dir:
S = dir(..);
N = {S.name}
which is simply equivalent to
N = {S(1).name, S(2).name, S(3).name, ...}
Or, consider a function with multiple optional input arguments:
opt = {'HeaderLines',2, 'Delimiter',',', 'CollectOutputs',true);
fid = fopen(...);
C = textscan(fid,'%f%f',opt{:});
fclose(fid);
Note how I pass the optional arguments as a comma-separated list. Remember how a comma-separated list is equivalent to writing var1,var2,var3,..., then the above example is really just this:
C = textscan(fid,'%f%f', 'HeaderLines',2, 'Delimiter',',', 'CollectOutputs',true)
with the added advantage that I can specify all of the optional arguments elsewhere and handle them as one cell array (e.g. as a function input, or at the top of the file). Or I could select which options I want simply by using indexing on that cell array. Note that varargin and varargout can also be useful here.
Function Outputs: In much the same way that the input arguments can be specified, so can an arbitrary number of output arguments. This is commonly used for functions which return a variable number of output arguments, specifically ndgrid and ind2sub. For example we can easily get all outputs of ndgrid, for any number of inputs (in this example three inputs and three outputs, determined by the number of elements in the cell array):
C = {1:3,4:7,8:9};
[C{:}] = ndgrid(C{:});
which is thus equivalent to:
[C{1},C{2},C{3}] = ndgrid(C{1},C{2},C{3});
Your Examples: Lets have a look at your examples in more detail:
r_data(:).MeanIntensity
We now know that this is a shorthand way to write this:
r_data(1).MeanIntensity, r_data(2).MeanIntensity, r_data(3).MeanIntensity, ...
and so you can use it anywhere that you would want a list of variables: inputs to a functions or an operator. One common application is with a concatenation operator (the colon you used is not strictly necessary if you want all elements, however you can use indexing if you want a subset of the elements):
vertcat(r_data.MeanIntensity)
which is equivalent to writing
vertcat(r_data(1).MeanIntensity, r_data(2).MeanIntensity, r_data(3).MeanIntensity, ... )
Summary: Just remember that in general a comma-separated list is not one variable, and that they are exactly what they say: a list (of variables) separated with commas. You use them all the time without even realizing it, every time you write this:
fun(a,b,c,d)
  3 Comments
Stephen23
Stephen23 on 17 Jan 2017
"Other than your post, how do I know what other variables will generate comma separated lists?" You read the documentation. The link that I gave at the top of my answer describes exactly two ways to generate comma separated list from a variable. I also gave you examples for both of these in my answer.
Stephen23
Stephen23 on 26 Oct 2021
Edited: Stephen23 on 31 Oct 2021
Apparently string arrays can also be used to create comma-separated lists. Just as with cell/struct derived comma-separated lists, the comma-separated list consists of the content of the string container (i.e. the character vectors stored within), and not of string scalars.
str = ["hello","world"]
str = 1×2 string array
"hello" "world"
mat = vertcat(str{:})
mat = 2×5 char array
'hello' 'world'
We can also assign to a string array using a comma-separated list, exactly as with cell/struct arrays:
[str{:}] = deal('it','works')
str = 1×2 string array
"it" "works"

Sign in to comment.

More Answers (0)

Categories

Find more on Cell Arrays in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!