Does the last element in a loop deserve a separate

2019-01-18 02:57发布

When reviewing, I sometimes encounter this kind of loop:

i = begin
while ( i != end ) {    
   // ... do stuff
   if ( i == end-1 (the one-but-last element) ) {
      ... do other stuff
   }
   increment i
}

Then I ask the question: would you write this?

i = begin
mid = ( end - begin ) / 2 // (the middle element)
while ( i != end ) {    
   // ... do stuff
   if ( i > mid ) {
      ... do other stuff
   }
   increment i
}

In my opinion, this beats the intention of writing a loop: you loop because there is something common to be done for each of the elements. Using this construct, for some of the elements you do something different. So, I conclude, you need a separate loop for those elements:

i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {    
   // ... do stuff
   increment i
}

while ( i != end ) {
   // ... do stuff
   // ... do other stuff
   increment i
}

Now I even saw a question on SO on how to write the if-clause in a nice way... And I got sad: something isn't right here.

Am I wrong? If so, what's so good about cluttering the loop body with special cases, which you are aware of upfront, at coding time?

13条回答
叛逆
2楼-- · 2019-01-18 03:42

I came to a realization that when I put special cases in a for loop, I'm usually being too clever for my own good.

查看更多
三岁会撩人
3楼-- · 2019-01-18 03:42

I prefer to simply, exclude the element from the loop and give a spearate treatment outside the loop

For eg: Lets consider the case of EOF

i = begin
while ( i != end -1 ) {    
   // ... do stuff for element from begn to second last element
   increment i
}

if(given_array(end -1) != ''){
   // do stuff for the EOF element in the array
}
查看更多
做个烂人
4楼-- · 2019-01-18 03:43

Of course, special-casing things in a loop which can be pulled out is silly. I wouldn't duplicate the do_stuff either though; I'd either put it in a function or a macro so I don't copy-paste code.

查看更多
该账号已被封号
5楼-- · 2019-01-18 03:49

The special case should be done outside the loop if it is only to be performed once.

However, there may be an index or some other variable(s) that are just easier to keep inside the loop due to scoping. There may also be a contextual reason for keeping all the operations on the datastructure together inside the loop control structure, though I think that is a weak argument on its own.

查看更多
对你真心纯属浪费
6楼-- · 2019-01-18 03:50

Its just about using it as per need and convenience. There is as such no mentions to treat elements equally and there is certainly no harm clubbing the features which language provides.

查看更多
你好瞎i
7楼-- · 2019-01-18 03:52

I think you have it entirely nailed. Most people fall into the trap of including conditional branches in loops, when they could do them outside: which is simply faster.

For example:

if(items == null)
    return null;

StringBuilder result = new StringBuilder();
if(items.Length != 0)
{
    result.Append(items[0]); // Special case outside loop.
    for(int i = 1; i < items.Length; i++) // Note: we start at element one.
    {
        result.Append(";");
        result.Append(items[i]);
    }
}
return result.ToString();

And the middle case you described is just plain nasty. Imagine if that code grows and needs to be refactored into different methods.

Unless you are parsing XML <grin> loops should be kept as simple and concise as possible.

查看更多
登录 后发表回答