进行审核时,我有时会遇到这样的循环方式:
i = begin
while ( i != end ) {
// ... do stuff
if ( i == end-1 (the one-but-last element) ) {
... do other stuff
}
increment i
}
然后,我问一个问题:你写的吗?
i = begin
mid = ( end - begin ) / 2 // (the middle element)
while ( i != end ) {
// ... do stuff
if ( i > mid ) {
... do other stuff
}
increment i
}
在我看来,这个节拍编写循环的意图:你循环,因为有共同的每个元素做一些东西。 利用这种结构,某些元素的,你做不同的事情。 所以,我的结论,你需要这些元素单独的循环:
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
}
现在,我甚至看到一个问题,关于如何写上SO if
-clause在一个不错的办法......而且我得到了伤心:自己是不是就在这里。
我错了吗? 如果是这样,什么是关于混乱的循环体有特殊的情况,这你是知道的前期,在编码时间这么好?
Answer 1:
@xtofl,
我同意你的关心。
千万次我遇到过类似的问题。
无论是开发人员添加了特殊处理的第一个或最后一个元素。
在大多数情况下,这是值得从startIdx + 1或endIdx只是循环- 1元,甚至一个长的环路分割成多个更短的循环。
在非常罕见的情况下,这是不可能的分裂循环。
在我看来罕见的事情应该循环尽可能之外处理。
Answer 2:
我不认为这个问题应该由一个原则回答(例如,“在一个循环中,平等地对待每一个元素”)。 相反,你可以看看两个因素来评估,如果实现的好坏:
- 运行有效性 - 并编译后的代码运行速度快,或将其更快地做不同?
- 代码的可维护性 - 它是容易的(另一开发商),了解这里发生了什么?
如果是更快的代码是在一个循环中做的一切更具可读性,这样做的。 如果是慢,不易阅读,另一种办法来做。
如果是更快,更可读,或慢,但更易读,找出你的具体情况,其中的因素更重要,然后再决定如何循环(或不循环)。
Answer 3:
我知道我已经看到了这一点,当人们试图加入一个数组的元素融入到一个逗号分隔字符串:
for(i=0;i<elements.size;i++) {
if (i>0) {
string += ','
}
string += elements[i]
}
你要么有,如果从句中有,否则你必须在年底再次复制串+ =行。
在这种情况下,显而易见的解决方案是
string = elements.join(',')
但是join方法做内部同一回路。 并没有总是做你想要什么的方法。
Answer 4:
我看破了,当我把特殊的情况下在for循环中,我通常是为了我好太聪明了。
Answer 5:
在您发布的最后一个片段,你是重复的代码// ....做的东西。
它使保持2个循环,当你有一组不同的指数完全不同的操作感。
i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {
// ... do stuff
increment i
}
while ( i != end ) {
// ... do other stuff
increment i
}
这种情况不是这样,你仍然要保持一个单回路。 然而事实是,你仍然保存(结束 - 开始)/ 2个比较。 所以,把它归结为您是否希望你的代码看起来整齐,或者您想节省一些CPU周期。 电话是你的。
Answer 6:
我认为你有这完全钉。 大多数人陷入其中包括循环的条件分支,什么时候才能外做他们的陷阱:这简直是快 。
例如:
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();
而你所描述的情况中只是普通的讨厌 。 试想一下,如果是码长,需要重构到不同的方法。
除非你解析XML <笑容>回路应尽可能简洁明了越好。
Answer 7:
我认为你是对有关环路被旨在对付同样的所有元素。 不幸的是,有时也有特殊情况,虽然这些应与内环路通过if语句构造处理。
如果有很多的特殊情况下,虽然你也许应该想想未来了一些方法来应对两套不同的独立的结构元素。
Answer 8:
我喜欢简单,排除环路中的元素,给循环外的spearate治疗
对于例如:让我们考虑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
}
Answer 9:
当然,这可以拉出一个循环特殊外壳的事情是愚蠢的。 我不会重复do_stuff要么虽然; 我想无论是把它放在一个函数或宏,所以我不要复制粘贴代码。
Answer 10:
我不愿看到的另一件事是对情况的模式 :
for (i=0; i<5; i++)
{
switch(i)
{
case 0:
// something
break;
case 1:
// something else
break;
// etc...
}
}
我在实际的代码看到了这一点。
Answer 11:
哪一个性能更好?
如果项目的数量是非常大的话,我会一直循环一次,尤其是如果你要对每一个项目进行一些操作。 评估条件的成本很可能会小于循环两次。
哎呀,你当然不循环两次......在这种情况下,两个循环最好。 但是,我认为,首要考虑的应该是性能。 有没有需要承担的条件在循环(N次),如果你可以通过循环边界(一次)的简单操作划分工作。
Answer 12:
特殊情况应外循环来完成,如果它只是执行一次。
然而,也有可能是指数或其他变量(一个或多个),它们只是更容易保持环路内由于作用域。 也有可能是为了保持所有的操作上的数据结构一起循环控制结构中的上下文的原因,但我认为这是对自己的一个薄弱的论据。
Answer 13:
它只是用它按需要和方便。 有这样没有提到平等对待的元素,当然没有什么坏处泡吧的语言提供的功能。
文章来源: Does the last element in a loop deserve a separate treatment?