How to operate on comma separated lists ?

327 views (last 30 days)
RuiQi
RuiQi on 17 Jan 2017
Edited: Stephen on 31 Oct 2021
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
Stephen
Stephen on 17 Jan 2017
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

Stephen
Stephen on 17 Jan 2017
Edited: Stephen on 26 Oct 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
2) from a cell array:
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 picked 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 with a concatenation operator (the colon you used is not necessary if you want all elements: you can use indexing if you want a subset of the elements):
vertcat(r_data.MeanIntensity)
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
Stephen
Stephen on 26 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)

Community Treasure Hunt

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

Start Hunting!