在下面的示例中,终止所有嵌套循环的最佳方法是什么。一旦if语句为true,我想终止外部for语句(使用I)。换句话说,我需要整个循环来停止。有没有比将I设置为10更好的方法?
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
}
}
答案 0 :(得分:32)
我会将此重构为方法,只需在需要时调用return
。
你也可以使用goto
,而 使用goto
就可以了,但是它不受欢迎。哪个是愚蠢的;这种情况是 为什么它存在于语言 。
void DoSomeStuff()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return;
}
}
}
}
...somewhere else...
DoSomeStuff();
答案 1 :(得分:15)
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something)
goto endOfTheLine;
}
}
}
endOfTheLine:
Console.WriteLine("Pure evilness executed");
答案 2 :(得分:14)
假设您要退出所有循环,您可以将其重构为更结构化的内容:
bool done = false;
for (int i = 0; i < 10 && !done; i++) {
for (int a = 0; a < 10 && !done; a++) {
for (int b = 0; b < 10 && !done; b++) {
if (something) {
done = true;
continue;
}
}
}
}
答案 3 :(得分:10)
如果循环体不产生副作用,而只是寻找“某事物”为真的第一个值,那么可以通过首先消除所有循环来解决问题。
var query = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
where something(I, A, B)
select new { I, A, B };
var result = query.FirstOrDefault();
if (result == null)
{
Console.WriteLine("no result");
}
else
{
Console.WriteLine("The first result matching the predicate was {0} {1} {2},
result.I, result.A, result.B);
}
但如果循环有副作用,请不要这样做;查询是放置副作用的一个非常糟糕的地方。如果内循环有副作用,那么你可以这样做:
var triples = from I in Enumerable.Range(0, 10)
from A in Enumerable.Range(0, 10)
from B in Enumerable.Range(0, 10)
select new { I, A, B };
foreach(var triple in triples)
{
if (something(triple.I, triple.A, triple.B))
break;
DoSomeSideEffect(triple.I, triple.A, triple.B);
}
现在只有一个循环可以突破,而不是三个。
答案 4 :(得分:3)
为什么不这样做:
for (int I = 0; I < 10 || !something; I++)
{
for (int A = 0; A < 10 || !something; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
{
I=10;
break;
}
}
}
}
答案 5 :(得分:3)
您总是可以利用for
中存在条件语句的事实:
bool working = true;
for (int i=0; i<10 && working; i++)
{
for (int j=0; j<10 && working; j++)
{
for (int k=0; k<10 && working; k++)
{
Console.WriteLine(String.Format("i={0}, j={1}, k={2}", i,j,k));
if (i==5 && j==5 && k==5)
{
working = false;
}
}
}
}
答案 6 :(得分:2)
我会倾向于goto
,否则你将不得不退出每个循环:
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
break;
}
if (something)
break;
}
if (something)
break;
}
答案 7 :(得分:2)
如果这是方法中的最后一项任务,则可以在条件为真时返回。 否则你必须将所有值都设为最大值
if (something)
{
I=10;
B=10;
A=10;
break;
}
答案 8 :(得分:2)
for (int I = 0; I < 10; I++) {
for (int A = 0; A < 10; A++) {
for (int B = 0; B < 10; B++) {
if (something){
B=13;
A=13;
I=13;
}
}
}
}
非常原始的解决方案。
答案 9 :(得分:2)
简单的解决方案是将嵌套循环重构为一个单独的方法,相关的返回类型就是你想知道的那一点:
在我的情况下,我会假设你想要那个时候I,A和B的值,而不是一个Tuple。
// original method
...
var x = FindFirst()
...
// separate method
public Tuple<int,int,int> FindFirst()
{
for (int I = 0; I < 10; I++)
{
for (int A = 0; A < 10; A++)
{
for (int B = 0; B < 10; B++)
{
if (something)
return Tuple.Create(I,A,B);
}
}
}
return null;
}
如果您需要将任何其他状态传递给方法(对于边界或某些位),只需将它们作为参数传递。
如果你想处理以不同的方式找不到第一个,那么
bool TryFindFirst(out Tuple<int,int,int> x)
将成为候补。
作为使用大写字母表示变量名称(特别是单字母)的旁注,在c#(和许多其他语言)中被认为是不好的风格
答案 10 :(得分:2)
我不知道C#
是否支持它,但有些语言支持:
break n;
其中 n
是要中断的嵌套循环的数量。
答案 11 :(得分:1)
你总能满足循环期望:
if(something) B = 10
编辑:(看来您通过编辑将其包含在帖子中)
如果您不喜欢它的外观,可以包装一个函数,例如:
满足式(B,10)
然后它看起来更干净,但实际上并不需要。
答案 12 :(得分:1)
另一种可能性是对所有for循环中的isSomething进行级联检查。 你添加
if (something)
break;
所有3个循环中的
答案 13 :(得分:1)
就我个人而言,我会选择上面的Paxdiablo方法(+1为此),但另一种选择在下面 - 这取决于当“某事”是真的时,OP需要知道I,A和B数是什么,因为iab是在循环中声明的,我猜不是。
bool done = false;
int i, a, b;
for (i = 0; i < 10 ; i++) {
for (a = 0; a < 10 ; a++) {
for (b = 0; b < 10 ; b++) {
if (something) {
done = true;
break;
}
}
if (done) break;
}
if (done) break;
}
// i, a and B are set to the last numbers where "something" was true