2

I thought that if I write

for x = cell_array
    ...
end

then the loop will run over the elements of cell_array, but in the following case it doesn't:

>> tags

tags = 

    'dset3'
    'dset4'
    'cpl1'

>> class(tags)

ans =

cell

>> for t = tags
     tmp = t{:}  %No semicolon: i.e. print it.
   end

tmp =

dset3

So it only works for the first element.

What's the problem?

Evgeni Sergeev
  • 22,495
  • 17
  • 107
  • 124
  • If you read the answers to the duplicate you might learn what you're doing wrong. There are many examples of the proper use of a cell array there and the two answers here are pretty much duplicated there. – horchler Feb 07 '14 at 17:55
  • @horchler My answer here explains the key to the confusion, which was the behaviour of the `{:}` expansion for single-column cell arrays. The other question doesn't mention that (no appearance of `{:}` on that page). – Evgeni Sergeev Feb 07 '14 at 21:17
  • 1
    for x = [cell_array{:}]; disp(x); end – user66081 Aug 18 '15 at 15:17
  • @user66081 The above doesn't work for e.g. `cell_array = {eye(1), eye(2)}`. Because it's trying to concat the arrays, resulting in `Error using horzcat Dimensions of matrices being concatenated are not consistent.` But this is good for well-behaved cell arrays, especially those that could have been plain matrices anyway. – Evgeni Sergeev Aug 21 '15 at 10:34
  • @EvgeniSergeev: true, thanks for pointing this out. – user66081 Aug 24 '15 at 12:55
  • 1
    This really shouldn't be marked duplicate. The other question asks what happens when you try to modify the iteration range at runtime. This question here is related to understanding cell expansion and whether iterations work over columns vs rows. Even if the answers happen to have some similarity, they are very different questions. – Kevin Holt Nov 06 '15 at 20:50

2 Answers2

9

According to the documentation, for x = cell_array will iterate over columns of the cell array.

The reason for the confusion in the question is to do with how the {:} expansion behaves:

>> a = {3;4}

a = 

    [3]
    [4]

>> b = a{:}

b =

     3

In the above, a{:} does something akin to typing in a comma-separated list where the elements are the elements of the cell array a. Except not quite! If we write such a list explicitly, we get:

>> c = 3,4

c =

     3


ans =

     4

Somehow, with the >> b = a{:}, the other elements of a are discarded silently, even if e.g. a = {1 2; 3 4}.

However, in other contexts, a{:} will expand into the full comma-separated list:

>> extra_args = {'*-'; 'linewidth'; 30};
>> plot(1:2, extra_args{:})
>> extra_args = {};
>> plot(1:2, extra_args{:})

This will do what it's intended to do.

Evgeni Sergeev
  • 22,495
  • 17
  • 107
  • 124
  • Interestingly, it doesn't just expand into a comma-separated list. If `a={}`, then `fprintf('%s %s\n', a{:}, 'b', 'c')` works, but `fprintf('%s %s\n', , 'b', 'c')` doesn't. I checked, and this also applies to user-created functions, so it's a feature of the language, rather than special processing done by the function `fprintf`. – Evgeni Sergeev Feb 10 '14 at 00:30
2

There is a nice function built into Matlab called cellfun. It allows you to "do something" with every element in the array in turn - regardless of its shape.

For example:

cellfun(@(x)fprintf(1,'%s',x), cellArray);

will loop over cellArray, and print the string in each cell.

You can also do one of the following things:

for x = cellArray(:)

  % do stuff to x

end
Floris
  • 45,857
  • 6
  • 70
  • 122