Best practice when coding for loops?

25 ビュー (過去 30 日間)
Vittorio
Vittorio 2015 年 11 月 6 日
編集済み: Matt J 2015 年 11 月 9 日
Hello everyone! When I code using for loops I always struggle between two methods of indexing. (Assume I can't do without using a for loop).
My favorite way is to use the for loop the "smart" way, by looping across an already defined vector, like:
MyVec = {'dog','cat','fish'};
for ind = MyVec
output = ComplicatedCalculations(ind);
disp(output);
end
I like this method because it is extremely flexible. Plus, it is very neat-looking code, one of the reasons I love MATLAB.
The problem is that this does not allow indexing if I also want to store the results of my calculations. So, holding a grudge, I often end up abandoning the smart way for the C-like way, which is method 2 below:
MyVec = {'dog','cat','fish'};
for ind = 1:length(MyVec)
output(ind) = ComplicatedCalculations(MyVec{ind});
disp(output(ind)); % do stuff
end
which does not look nearly as neat. So my question is: is there a way to bring together the best of both worlds, i.e. using MATLAB native smart way of for-looping, while allowing me to index the results and store them into a (possibly multi-dimensional) vector? Thanks!
  3 件のコメント
Kirby Fears
Kirby Fears 2015 年 11 月 6 日
編集済み: Kirby Fears 2015 年 11 月 6 日
The second method is best practice. As long as MyVec is used to determine the for-loop range (as you did in your example), it says to the code reader that MyVec is the loop's key. This makes code easy to follow.
If you're frustrated with repeating MyVec{ind} many times inside of your loop, you can store the value (such as MyElmt=MyVec{ind}) in a temporary variable at the start of each iteration.
You could also use a counter variable along with method 1, but it would look silly.
Vittorio
Vittorio 2015 年 11 月 6 日
Thanks Kirby! I agree with your comment. Actually, looking back at some codes I have found that I had used what I think you mention:
MyVec = {'dog','cat','fish'};
count = 1;
for ind = MyVec
output(count) = ComplicatedCalculations(ind);
count = count+1;
end
I agree, it looks a bit silly, but it is cleaner.

サインインしてコメントする。

採用された回答

Matt J
Matt J 2015 年 11 月 6 日
編集済み: Matt J 2015 年 11 月 6 日
I don't know if I agree that loop counters with non-numeric data are "smarter", but if you don't mind storing in struct form, you can do,
MyVec = {'dog','cat','fish'};
for ind = MyVec
output.(ind{1}) = ComplicatedCalculations(ind);
disp(output.(ind{1}));
end
  5 件のコメント
Vittorio
Vittorio 2015 年 11 月 6 日
That's an interesting idea. I am not limiting myself to strings, actually in most cases I deal with vectors like Jon mentioned. Still the code seems a bit obscure.
Walter Roberson
Walter Roberson 2015 年 11 月 6 日
編集済み: Walter Roberson 2015 年 11 月 6 日
Matt, this (the original code) only works if the strings happen to be valid identifier names.

サインインしてコメントする。

その他の回答 (2 件)

Walter Roberson
Walter Roberson 2015 年 11 月 6 日
Be careful! Your first example
MyVec = {'dog','cat','fish'};
for ind = MyVec
output = ComplicatedCalculations(ind);
disp(output);
end
results in a cell array with one element being passed to ComplicatedCalculations, whereas your second version has the content of the element being passed.
for does not always have the seemingly obvious behaviour when it is applied to something that is not a row vector. for ind = MyVec does the equivalent of
TMyVec = reshape(MyVec, size(MyVec,1), []);
for Tidx = 1 : size(TMyVec,2)
ind = TMyVec(:,Tidx);
...
end
Notice how if MyVec is a cell array, ind is going to end up a cell array as well. And notice that if the input has multiple rows then ind gets set to a column vector, even if the input was a vector (no automatic transpose to loop over the elements.)
Because of these factors and the fact that I need the index most of the time, I code with the index form nearly all of the time.
  1 件のコメント
Vittorio
Vittorio 2015 年 11 月 6 日
Agreed. My example did not want to focus on the cell array, it was just to show the flexibility that a for loop used that way gives me. Most times I actually work with numerical arrays so the problem does not apply. Still, that is a good point.

サインインしてコメントする。


Matt J
Matt J 2015 年 11 月 6 日
編集済み: Matt J 2015 年 11 月 6 日
The scenario assumed in the post is the kind where a loop can usually be avoided altogether in favor of cellfun,
output = cellfun(@ComplicatedCalculations, MyVec);
which of course is even more succinct than the loop.
If you can't implement a loop using cellfun, it usually means the body of the loop has many lines and statements and lots of different things being indexed. In that situation, I can't see how one particular choice of loop counter or another would be the main factor in how neat the code looks.
  2 件のコメント
Vittorio
Vittorio 2015 年 11 月 9 日
編集済み: Vittorio 2015 年 11 月 9 日
Thanks for bringing up cellfun, I did not know about it. One question: while the function is being applied to the elements of MyVec, I cannot do anything else, such as showing the result of the calculation to the command window?
PS: a lot of my problems stem from the fact that ComplicatedCalculations is a large code that I did not write, very old, very hard to modify, based on some questionable design choices. I could do a lot better if I had an easier function to deal with, but that's unfortunately not possible.
Matt J
Matt J 2015 年 11 月 9 日
編集済み: Matt J 2015 年 11 月 9 日
One question: while the function is being applied to the elements of MyVec, I cannot do anything else, such as showing the result of the calculation to the command window?
You can insert display commands inside ComplicatedCalculations(), or wrap it in another function that does so:
function out=myfun(in)
out=ComplicatedCalculations(in);
disp(out),
end
cellfun(@myfun, MyVec)
One thing I am not sure of is if the elements of MyVec will always be processed in sequential order, although I haven't been able to produce a case where it doesn't.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeData Type Conversion についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by