How does one concatenate cell arrays that are part of a cell array in MATLAB?

10,719

Solution 1

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{:}];

Solution 2

Try this

 allNames = arrayfun(@(x) x.name, [allData{:}], 'UniformOutput', false)

Omit the UniformOutput vararg for straight concatenation. This gives a cell output.

Share:
10,719
PengOne
Author by

PengOne

Updated on June 15, 2022

Comments

  • PengOne
    PengOne almost 2 years

    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!!

  • gnovice
    gnovice almost 13 years
    The operation [allData{:}] will only work if the elements of the cell array can be horizontally concatenated into a structure array, which would mean there was no real reason to use a cell array in the first place.
  • PengOne
    PengOne almost 13 years
    This is great if they are cell arrays of strings, but sadly I misled you. They are cell arrays of custom objects. Still, I may be able to get some mileage out of this approach. Thanks!
  • Richie Cotton
    Richie Cotton almost 13 years
    @PengOne: The moral of the story being "remember to provide sample data in your question".
  • Andrew Lazarus
    Andrew Lazarus almost 13 years
    @PengOne: note the [brackets]. But I'll try for a more generic solution.
  • PengOne
    PengOne almost 13 years
    @Richie Cotton: The object is defined over several files and many, many lines, so it only clouds the question which at the heart is simple: How can I concatenate cell arrays that themselves are cells in a cell array?
  • PengOne
    PengOne almost 13 years
    Tried this... result is a 1x3 cell array, each cell containing one of the cell arrays that I truly wish would just find a way to concatenate themselves!
  • gnovice
    gnovice almost 13 years
    @PengOne: I've updated my answer to deal more generally with objects as opposed to strings.
  • PengOne
    PengOne almost 13 years
    JessumCrow! The vertcat function worked (once I transposed correctly)! Thanks for this. I did not need to reshape for my example, but please leave it in your solution in case someone else beats his head against the wall on this one.
  • Andrew Lazarus
    Andrew Lazarus almost 13 years
    @PengOne, Not quite sure what you mean, but a possibility: By changing UniformOutput to true, you get array output. That is the default anyway. You may need to transpose the output to get a concatenated single string.