在锡兰中打破多个for循环

时间:2016-01-23 18:07:42

标签: ceylon

让我说我在锡兰有几个嵌套的for循环。如何摆脱所有循环:

variable Integer? something = null;
for (i in 0:3) {
  for (j in 0:3) {
    for (k in 0:3) {
      something = someFunction(i,j,k);
      if (something exists) {
        // break out of everything, we found it
      }
    }
  }
}

3 个答案:

答案 0 :(得分:6)

这样做的一种方法是将整个事物包装在一个闭包中,然后在想要突破所有内容时使用return调用它:

Integer? doLoops() {
  for (i in 0:3) {
    for (j in 0:3) {
      for (k in 0:3) {
        Integer? something = someFunction(i,j,k);
        if (something exists) {
          return something;
        }
      }
    }
  }
  return null;
}
Integer? something = doLoops();

因为Ceylon支持闭包,所以您还可以在定义doLoops的范围内读取和写入函数外的其他值。

答案 1 :(得分:5)

您可以改为使用理解和流处理语法:

Iterable<Integer?> stream = {
    for (i in 0:3) for (j in 0:3) for (k in 0:3) someFunction(i,j,k)
};

Integer? = stream.coalesced.first;

这将按预期工作,因为{ for ... }理解会创建一个懒惰评估的Iterable

iterable的coalesced属性返回另一个lazy iterable,它跳过原始中的所有null值。

然后只要求剩下的可迭代的第一个值,那就是你的答案。

答案 2 :(得分:3)

另一种方法是在else循环上使用for块:

shared void run() {
    variable Integer? x = null;
    for (i in 0:3) {
        for (j in 0:3) {
            for (k in 0:3) {
                value n = i*j*k;
                if (n > 18) {
                    x = n;
                    break;
                } else {
                    continue;
                }
            } else {
                continue;
            }
            break;
        } else {
            continue;
        }
        break;
    } else {
        x = null;
    }
    print(x);
}

一般来说,放置

else {
    continue;
}
break;

在每个for的结束后。

(注意:理想情况下,我的示例中指定的变量x,您自己的something - 不需要variable,因为它只分配了一次。但是, typechecker目前can’t prove that。)

它是如何工作的?如果该循环在没有任何else的情况下运行完成,则执行for循环后的break。在这种情况下,我们也希望continue外部循环;否则 - 也就是说,如果我们从内循环中断开 - 我们也希望从外部循环中break

使用ceylon/ceylon#3223中提出的以下语法可以更简洁地编写:

for (a in b) {
    for (x in y) {
        if (something) {
            break;
        }
    } then { // opposite of else: runs iff there was a break in the inner loop
        break;
    }
}

我不建议使用此解决方案,原因有三:

  • 它比闭包解决方案的可读性更低。 for {} else {}功能相当模糊,如果您不熟悉它,其含义并不明显,使得代码对于随意的读者来说难以理解。
  • 它在每个周围的循环(不仅仅是一次)中大量增加了代码,也让它变得难以理解。
  • 如果你想在内部循环之后的外部循环中有代码,你将不得不复制它:else块和它之后的代码都需要副本。