从多个嵌套循环退出的惯用法?

时间:2015-10-08 06:42:48

标签: matlab nested-loops break labelled-break

MATLAB documentation因此描述了break关键字:

  
      
  • break终止执行for或while循环。 break语句之后循环中的语句不会执行。
  •   
  • 在嵌套循环中,break仅从发生它的循环中退出。控制传递给该循环结束后的语句。
  •   

(我的重点)

如果要退出多个嵌套循环,该怎么办?其他语言(如Java)提供 labelled breaks ,它允许您指定控制流的传输位置,但MATLAB缺少这样的机制。

考虑以下示例:

% assume A to be a 2D array

% nested 'for' loops
for j = 1 : n
  for i = 1 : m
    if f(A(i, j)) % where f is a predicate
      break; % if want to break from both loops, not just the inner one
    else
      % do something interesting with A
    end
  end
  % <--- the break transfers control to here...
end
% <--- ... but I want to transfer control to here

从两个循环中退出的惯用方法(在MATLAB中)是什么?

3 个答案:

答案 0 :(得分:2)

我会说你的原始 特定的示例,而是使用线性索引和单个循环:

%// sample-data generation
m = 4;
n = 5;
A = rand(m, n);
temp = 0;

for k = 1:numel(A)
    if A(k) > 0.8 %// note that if you had switched your inner and outer loops you would have had to transpose A first as Matlab uses column-major indexing
      break; 
    else
      temp = temp + A(k);
    end
end

或几乎相同(但分支较少):

for k = 1:numel(A)
    if A(k) <= 0.8 %// note that if you had switched your inner and outer loops you would have had to transpose A first as Matlab uses column-major indexing
      temp = temp + A(k);
    end
end

我认为这个答案会因个案而异,并且没有一般适合所有惯用正确的解决方案,但我会根据您的问题以下列方式处理它(请注意这些所有都假设矢量化解决方案不实用,因为这是明显的首选)

  1. 缩小嵌套的尺寸,使用不break个或仅使用一个break(如上所示)。
  2. Don't use break at all因为除非你的谓词的计算费用很高且你的循环有很多次迭代,所以最后那些额外的迭代应该是免费的。
  3. 未通过set a flag and break at each level
  4. 或者最后将循环包装到函数中并调用return而不是break

答案 1 :(得分:1)

据我所知,内置没有这样的功能。但是,在大多数情况下,matlab不需要嵌套循环,因为它支持矢量化。在矢量化不起作用的情况下,循环通常很长且复杂,因此多次中断不会显着妨碍可读性。正如评论中所指出的,这里你不需要一个嵌套循环。矢量化可以解决问题,

        public Items(int iD, int droprarity, Random random)
        {
            Random = random;
            ID = iD;

当然可能有人声称for循环不再是慢的,但事实仍然是Matlab是柱重,并且在大多数情况下使用多个循环将包括非最佳维度的循环。矢量化解决方案不需要,因为他们可以使用智能方法来避免这种循环(如果输入是行向量,当然不能保持这种情况,因此避免这种情况也很好)。

答案 2 :(得分:0)

使用Python的最佳惯用方式(或您选择的毒药)并忘记了所有这些,但这是另一个故事。此外,我不再同意其他答案的矢量化声明。最近的matlab版本很快处理循环。你可能会感到惊讶。

我个人的偏好是故意提出一个例外,并在一个尝试和捕获块中支持它。

% assume A to be a 2D array
A = rand(10) - 0.5;
A(3,2) = 0;

wreaker = MException('Loop:breaker','Breaking the law');

try
    for j = 1 : size(A,1)
        % forloop number 1
        for i = 1 : size(A,2)
            % forloop number 2
            for k = 1:10
                % forloop number 3
                if k == 5 && j == 3 && i == 6
                    mycurrentval = 5;
                    throw(wreaker)
                end
            end
        end
    end
catch
    return % I don't remember the do nothing keyword for matlab apparently
end

您可以更改try catch缩进的位置,以回退到您选择的循环。同样通过杀死小猫,您可以编写自己的异常,以便根据嵌套计数标记异常,然后您可以监听它们。丑陋虽然比在我看来有if条款的计数器或自定义变量更漂亮,但仍然没有尽头。

请注意,这正是matlab驱使许多人疯狂的原因。它以一种非常类似的方式默默地抛出异常,并且在经过时,您会得到最后一个随机选择函数的无意义错误,例如某些微分方程求解器中的大小不匹配等。在阅读了很多matlab工具箱源代码后,我实际上学到了所有这些东西。