In ifs inside for loops, prefer checking for true, or for false and continue?

I’m discussing this with a work colleague.
Say we want to sum the numbers from 0 to 9 skipping 5.
He prefers this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>int sum = 0;
for(int i = 0; i < 10; ++i)
{
if(i == 5)
{
continue;
}
sum += i;
}
</code>
<code>int sum = 0; for(int i = 0; i < 10; ++i) { if(i == 5) { continue; } sum += i; } </code>
int sum = 0;
for(int i = 0; i < 10; ++i)
{
    if(i == 5)
    {
        continue;
    }

    sum += i;
}

I prefer this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>int sum = 0;
for(int i = 0; i < 10; ++i)
{
if(i != 5)
{
sum += i;
}
}
</code>
<code>int sum = 0; for(int i = 0; i < 10; ++i) { if(i != 5) { sum += i; } } </code>
int sum = 0;
for(int i = 0; i < 10; ++i)
{
    if(i != 5)
    {
        sum += i;
    }
}

Any reason to prefer one over the other?
Cyclomatic complexity is the same in both cases, right?

5

As it stands right now (a single condition) I don’t see much reason to prefer one over the other, but I’d probably prefer the second as slightly simpler.

When, however, your set of conditions are more complex, some variant of the first can be preferable, often by a wide margin. Consider something like:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>for (...) {
if (i != 5 && (i%2!=0) && i>99 && i<1000 && (i%17 !=3))
sum += i;
}
</code>
<code>for (...) { if (i != 5 && (i%2!=0) && i>99 && i<1000 && (i%17 !=3)) sum += i; } </code>
for (...) {
    if (i != 5 && (i%2!=0) && i>99 && i<1000 && (i%17 !=3))
        sum += i;     
}

vs:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>for (...) {
if (i==5)
continue;
if (i%2 == 0)
continue;
if (i<100 || i > 999)
continue;
if (i % 17 == 3)
continue;
process(i);
}
</code>
<code>for (...) { if (i==5) continue; if (i%2 == 0) continue; if (i<100 || i > 999) continue; if (i % 17 == 3) continue; process(i); } </code>
for (...) {
    if (i==5)
        continue;
    if (i%2 == 0)
        continue;
    if (i<100 || i > 999)
        continue;
    if (i % 17 == 3)
        continue;
    process(i);
}

In this case, the latter seems (to me) more understandable and maintainable. It lets us group the items that are logically connected (the range, 100…1000) together, but keep those that aren’t so closely related separate so each can be analyzed on its own more easily. It also fits closely with a pattern I use in quite a few functions that basically works out to something like:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>function(x, y, z) {
if (!preconditions(x, y, z))
// return an error or (preferably) throw an exception
// now do processing on x, y, z
}
</code>
<code>function(x, y, z) { if (!preconditions(x, y, z)) // return an error or (preferably) throw an exception // now do processing on x, y, z } </code>
function(x, y, z) { 
    if (!preconditions(x, y, z))
        // return an error or (preferably) throw an exception

    // now do processing on x, y, z
}

Although in your case it’s a loop body instead of a function per se, you still end up with the same basic pattern: assure that some set of preconditions is met, and then if (and only if) it s, process the data.

1

I personally would go with the first example, given your task. The first example more closely matches your original problem statement. The 2nd requires a little bit more mental parsing to determine if it fulfills your problem statement.

Look at how you worded what is going on: “Sum the numbers from 0 to 9 skipping 5”. That is exactly what the first statement does. The 2nd doesn’t read quite the same way.

Ultimately, what is right is going to depend on the context of the greater problem you are going to solve. The less thinking you have to do to verify it’s doing what it is supposed to, the better.

6

My suggestion would be to extract that logic out into a method so that if you add more conditions or even change your condition it is easier to maintain in one place + it is more testable.

The reason I am suggesting that is because I am assuming this is not the actual problem but it is a more simplified version of your problem that you have narrowed it down to demo it here.

If, however, my assumptions are wrong then it would still be a good idea to extract it out because it makes it a lot more readable and understandable (mostly because of the method name and the variable names) – so that when you come back to it after a while it is still easy to grasp and know what you meant when you wrote it the first time.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> private void sumItUp()
{
int sum = 0;
for (int numberToAddToSum = 0, i = 0; i < 10; numberToAddToSum = SkipIfNextOneIsFive(i), i++)
{
sum += numberToAddToSum;
}
}
private int SkipIfNextOneIsFive(int i) { return i + 1 == 5 ? 0 : ++i; }
</code>
<code> private void sumItUp() { int sum = 0; for (int numberToAddToSum = 0, i = 0; i < 10; numberToAddToSum = SkipIfNextOneIsFive(i), i++) { sum += numberToAddToSum; } } private int SkipIfNextOneIsFive(int i) { return i + 1 == 5 ? 0 : ++i; } </code>
    private void sumItUp()
    {
        int sum = 0;

        for (int numberToAddToSum = 0, i = 0; i < 10; numberToAddToSum = SkipIfNextOneIsFive(i), i++)
        {
            sum += numberToAddToSum;
        }
    }

    private int SkipIfNextOneIsFive(int i) { return i + 1 == 5 ? 0 : ++i; }

Both of those code fragments are doing way too much work. You can replace them with int sum = 40; (in fact, if you gave those code fragments to a compiler, that’s basically what the compiler would do). There’s a famous trick for summing up the first n integers I used to do it in my head, but if you didn’t know the trick and had no calculator handy, you could work it out with pen and paper in about the same amount of time it would take to type up that code. So the problem, as stated, isn’t something you should be writing a program for at all.

Of course, you aren’t asking about only that one example problem. What problem are you actually trying to solve? The question overspecifies a bit, so I’ll just guess that you’re either (a) going for something that sums up all the consecutive integers over a range except for a specified one, or (b) you’re going for summing up all the consecutive integers in a range, except for a range in the middle.

If you want (a), then you can just subtract the specified number from the range. If you want (b), then you can break the large range into a bottom half and a top half and deal with each separately. So, in either case, we want something that can sum up a range of integers.

If you know the famous formula for summing up the first n integers (n*(n+1)/2), and you know how it works, it isn’t hard to come up with a formula for a range ((top-bottom+1)*(top+bottom)/2). If not, there’s the obvious and straightforward way of doing it with for loops.

If we write a function that does that (with either method), we can rewrite the original problem as sum_range(0,9) - 5 or sum_range(0,4) + sum_range(6,9). It turns out we didn’t need any ifs or continues, and, depending on how we wrote it, maybe no for loop either.

If your question is really about which keyword to use when nested inside a construct using a specific keyword which is nested inside another construct using another specific keyword, then I don’t think your question really has an answer, and that trying to figure out how to program by looking at which keywords nest inside which other keywords is never going to be useful.

(For those interested, the formula works like this: say we’re trying to add up all the integers from 1 to 100. 1+100 = 101, 2+99 = 101, 3+98 = 101, and so on, so we could just multiply 101 by the number of pairs, and the number of pairs is the number of numbers being added / 2. In this case, top = 100, bottom = 1, top+bottom = 101, and the number of pairs is (top-bottom+1)/2 = n/2 = 50.)

Technically he will have one more line of execution for the continue statement. Otherwise, the code is identical. It is O(n) in both cases.

2

Any reason to prefer one over the other?

At some places and in some languages, the use of continue and break are frowned upon as glorified gotos. They make it harder to read the code since you need to stop and then find the end of the loop you’re in rather than noting the condition and reading along.

The second version will work in pretty much any language too. continue isn’t always available.

1

A for loops natural tendency is to “continue” and as others have pointed out, it’s an extra line of code.

In 15 years of writing code I have MAYBE used continue (in any language) 3 times; and none of that was recent. It’s simply not a necessary construct as you quickly realize.

3

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật