首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从多个嵌套循环中退出的惯用方式?

从多个嵌套循环中退出的惯用方式?
EN

Stack Overflow用户
提问于 2015-10-08 06:42:47
回答 3查看 206关注 0票数 1

因此,MATLAB文档描述了break关键字:

  • break终止for或while循环的执行。中断语句后循环中的语句不执行。
  • 在嵌套循环中,中断只退出在其中发生的循环。控件传递给该循环结束后的语句.

(我强调)

如果您想从多个嵌套循环中退出呢?其他语言,如Java,提供了https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html,它允许您指定要在何处传输控制流,但是MATLAB缺乏这样的机制。

请考虑以下示例:

代码语言:javascript
复制
% 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中)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-08 07:02:47

对于您的原始示例,我想说的是,应该使用线性索引和一个循环:

代码语言:javascript
复制
%// 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

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

代码语言:javascript
复制
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. 根本不用休息,因为除非您的谓词的计算非常昂贵,并且您的循环有很多迭代,否则这些额外的迭代应该实际上是免费的。
  3. 设置一个旗子,并在每个级别中断。失败了。
  4. 或者最后将循环包装成一个函数,调用return而不是break
票数 2
EN

Stack Overflow用户

发布于 2015-10-08 07:13:30

据我所知,没有内置这种功能。然而,在大多数情况下,matlab不需要嵌套循环,因为它支持矢量化。在矢量化不起作用的情况下,循环大多是长而复杂的,因此多次中断不会严重影响可读性。正如注释中所指出的,这里并不需要嵌套循环。矢量化就能达到目的,

代码语言:javascript
复制
m = 5;
n=4;
x = rand(m,n);
tmp = find(x>0.8, 1, 'first');
if (isempty(tmp))
   tmp = m*n+1;
end
tmp = tmp-1;
tot = sum(x(1:tmp));

当然,可能有人声称for循环不一定是慢的,但事实仍然是,Matlab的列很重,并且在大多数情况下使用多个循环将包括在非最优维度上循环。向量化的解决方案不要求使用智能方法来避免这样的循环(如果输入是行向量,那么这种循环当然不存在,因此避免这种情况也是好的)。

票数 1
EN

Stack Overflow用户

发布于 2015-10-08 09:30:54

使用Python (或您所选择的毒药)并忘记这一切的最好的惯用方式,但这是另一个故事。另外,我不同意其他答案的向量化说法。最近的matlab版本处理循环相当快。你可能会大吃一惊。

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

代码语言:javascript
复制
% 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

您可以将尝试捕获缩进的位置更改为回到您选择的循环。另外,通过杀死小猫,您可以编写自己的异常,这样它们就可以根据巢数来标记异常,然后您就可以监听它们了。在我看来,丑陋是没有尽头的,尽管它比带有if子句的计数器或自定义变量更漂亮。

请注意,这正是为什么matlab使许多人发疯的原因。它以一种非常相似的方式悄悄抛出异常,在经过时,对最后一个随机选择的函数得到一个无意义的错误,例如一些微分方程求解器中的大小不匹配。事实上,我在阅读了很多matlab工具箱源代码之后,才学到了所有这些东西。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33008402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档