MATLAB Answers

Design choice for iterating over a cell array

224 views (last 30 days)
I discovered that it was possible to iterate over a cell array in Matlab:
for x = {1, "foo", [1,2]}
x
end
However, for each iteration, x is a 1x1 cell array containing an element of the cell array over which we iterate, instead of (as it would be logical) directly the element of the cell array. I.e., x takes the values {1}, {"foo"}, {[1,2]}, instead of 1, "foo", [1,2]. It is a bit cumbersome to have to call x{1} each time I want to use the value from the cell array, instead of simply typing x.
Is there any good reason why the language was designed this way?

  1 Comment

Stephen Cobeldick
Stephen Cobeldick on 27 Mar 2018

"Is there any good reason why the language was designed this way?"

Consistency. All arrays can be iterated over, and for all arrays the index variable is one element (or one column) of that array, no matter what class. People often forget that for actually loops over the columns, which would lead to awkward bugs/inconsistencies/... if the contents of cell arrays were returned in the index.

Sign in to comment.

Accepted Answer

Philip Borghesani
Philip Borghesani on 27 Mar 2018
Edited: Philip Borghesani on 28 Mar 2018
There was not much choice in how the language could do it. For was initially defined to loop over the columns of the input matrix. Examine these two lines of code and think about what would happen if the for loop tried to dereference the cell.
>> for x=[1,2;4,5],x,end
x =
1
4
x =
2
5
>> for x={1,2;4,5};x,end
x =
2×1 cell array
{[1]}
{[4]}
x =
2×1 cell array
{[2]}
{[5]}

  3 Comments

Philip Borghesani
Philip Borghesani on 3 Apr 2018
I forgot to mention that if you are using a recent version of MATLAB and have a cellstr you might look into using a string array which works nicely:
>> for x=["one","two","three"],x,end
x =
"one"
x =
"two"
x =
"three"
J. Alex Lee
J. Alex Lee on 9 Aug 2018
Interesting tidbit...is this a vestige of the row-oriented array definition of Matlab, so that the concept of iterating through a default 1D array worked as intended? (I was always curious why the syntax failed for iterating through column vectors, and now I know!)
Other than for intuition based on the 1D row vector, is it more generally useful to define "for" this way? For "consistency", this works for multidimensional arrays, but doesn't it seem completely arbitrary to choose to iterate on the 2nd dimension?
Another way in which this "consistency" argument violates my intuition is that being allowed to use linear indexing of arrays suggests to me that "for" would iterate on the linear index of an array.
If you wanted to iterate on the linear index, you might think you can do
X = rand(2,3,4)
for x in X(:)
x
end
but of course this returns a column vector, so you would have to first transpose to get what you want...for full consistency, shouldn't the (:) construct return a row so that "all elements" is equivalent to "all columns"?
J. Alex Lee
J. Alex Lee on 9 Aug 2018
And to the point about string(array)s, they are a welcome data type to Matlab for other reasons, but most Matlab functions and methods that return lists of non-numeric things that one might want to iterate through in a cell array of characters rather than a string array...and they return these "lists" in columns (I just found that sometimes it returns rows to add to my confusion, e.g., the keys in a containers.Map). To Alec's point, there are still cumbersome coding adjustments to get what you want, e.g.
for prop = transpose(string(properties(myclass)))
prop
end
or working with an intermediary integer index
myprops = properties(myclass);
for i = 1:numel(myprops)
prop = myprops(i);
end
For a specific use case that I imagine isn't that uncommon, iterating through containers.Map entries is bulky one way or another because you either have to convert to string to iterate nicely and convert back to char to access the map contents, or convert the 1x1 cell to char (or append the {1}, which I think is semantically ugly)

Sign in to comment.

More Answers (1)

Bob Nbob
Bob Nbob on 27 Mar 2018
I can't really speak to why the language was designed in that manner, but I can say that there are times where you want to consider the cell as a whole, rather than just the contents, and the specific value of x that you are calling has been written to call the cell as a whole.
Additionally, you will want to leave it in this manner, because you have different classes of data contained within your cells. If you attempted to assign x as the contents of the cell, rather than the cell itself, you would receive an error after your first iteration because you would be attempting to assign a string class value to a double class variable. Leaving x as a cell, and requiring the calling of the contents, allows you to switch smoothly between class types within the cell.

  4 Comments

Show 1 older comment
Bob Nbob
Bob Nbob on 27 Mar 2018
Would that work with x being the index? I've never tried to redefine my index within a loop.
Stephen Cobeldick
Stephen Cobeldick on 27 Mar 2018
@Bob Nbob: it is allowed to redefine the index. Pay attention to the warning messages though: the editor will offer to hide the warning for that line.
Rik
Rik on 27 Mar 2018

Is that a setting buried somewhere deep? Because for me it doesn't offer to hide the warning, it just suggests it as a possible course of action.

Sign in to comment.

Products