I have a cell array allData
which is Nx1. Each cell contains a structure with a names
property (the name is a custom object, but think of it as a cell array of strings if you like). I would like to create a single cell array that contains all of the names. For example, if N=3, so that allData
is a 3x1 cell array, then the following would accomplish my goal:
A = allData{1};
B = allData{2};
C = allData{3};
allNames = [A.names B.names C.names];
The problem with this approach is that N is large and changes depending on the input, so I'm hoping that there is a clever way to do this using cellfun
, but everything that I've tried fails (e.g. it doesn't work to do allNames = [cellfun(@(x) {x.names}, allData)];
).
UPDATE: Thanks to the suggested solutions, I can get everything into one cell array where each cell contains a cell array. My goal here is to concatenate these. More or less, what I have is:
{A.names B.names C.names}
and what I want and cannot seem to get is
{A.names{1} A.names{2} ... A.names{end} B.names{1} ... B.names{end} ...}
SOLUTION: I needed pieces of each answer below, so here's the solution that worked for me:
from Andrew Lazarus:
allNames = arrayfun(@(x) x.name, [allData{:}], 'UniformOutput', false);
then, from gnovice:
allNames = vertcat(allNames{:});
Thanks to both!!
You can use the square bracket operator [] to concatenate. For example, [A,B] or [A B] concatenates arrays A and B horizontally, and [A; B] concatenates them vertically.
C = vertcat( A1,A2,…,An ) concatenates A1 , A2 , … , An vertically. vertcat is equivalent to using square brackets for vertically concatenating arrays. For example, [A; B] is equal to vertcat(A,B) when A and B are compatible arrays.
Description. newStr = join( str ) combines the text in str by joining consecutive elements of the input array, placing a space character between them. str can be a string array or a cell array of character vectors. newStr has the same data type as str .
A = cellfun('size',C,k) returns the size along the k th dimension of each element of C . A = cellfun('isclass',C,classname) returns logical 1 ( true ) for each element of C that matches the classname argument. This syntax returns logical 0 ( false ) for objects that are a subclass of classname .
There are a few more details about your cell contents that would be needed for a more general solution, but if the names
property always returns a cell array of strings, and if your structures are all scalars (i.e. 1-by-1 structure arrays), then the following solution using CELLFUN, CHAR, and CELLSTR will give you an N-by-1 cell array of strings allNames
containing all of your names:
allNames = cellfun(@(x) {char(x.names)},allData);
allNames = cellstr(char(allNames{:}));
And here's an example where allData
contains three different structures:
>> allData{1} = struct('names',{{'hello'}},'junk',1:3);
>> allData{2} = struct('names',{{'hi' 'yo' 'hey' 'whassup'}});
>> allData{3} = struct('names',{{'howdy';'aloha'}},'junk',4);
>> allNames = cellfun(@(x) {char(x.names)},allData);
>> allNames = cellstr(char(allNames{:}))
allNames =
'hello'
'hi'
'yo'
'hey'
'whassup'
'howdy'
'aloha'
EDIT:
Generalizing to the case where the names
property returns a cell array of objects, not necessarily strings, you can try this solution which reshapes each cell array into an M-by-1 cell array, then vertically concatenates all of them into an N-by-1 cell array of objects:
allNames = cellfun(@(x) {reshape(x.names,[],1)},allData);
allNames = vertcat(allNames{:});
Or, if you would rather end up with a 1-by-N cell array of objects, you can do this:
allNames = cellfun(@(x) {reshape(x.names,1,[])},allData);
allNames = [allNames{:}];
Try this
allNames = arrayfun(@(x) x.name, [allData{:}], 'UniformOutput', false)
Omit the UniformOutput vararg for straight concatenation. This gives a cell output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With