清除基于for循环的索引中第一个元素的清晰方法


9

我有一个for循环,在这里必须跳过基于零的数组中的第一个元素。

其中哪一个更清楚地表明了我的意图?

for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

要么

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}

28
两者都不$i=2-1是更好的方法。:/
yannis '16

7
我可能会选择第一个选项并添加一条注释,以解释为什么必须跳过第一个元素。
文森特·萨瓦德

3
清除是我的目标,所以我编辑了问题。这更清楚吗?
Tomas Zubiri

10
不使用PHP是更好的方法。

3
PHP是否具有foreach构造?您可以foreach ($i in range(1, count))(在PHP中看起来像那样)。或类似的事情foreach ($item in array.skip(1)),C#的人会做。
usr

Answers:


23

我都讨厌

谁说您可以使用幻数?如果您要以1的偏移量开始,那么告诉我们为什么要以1的偏移量开始。添加同样神奇的零对我来说没有任何意义。

这是有效载荷偏移量吗?您要转换为以null结尾的c字符串的此pascal字符串吗?请告诉我们发生了什么事。

抱歉,但是我浪费了很多职业生涯,无法解释像这样的毫无意义的谜团,而我对它们的耐心已经淡了。是一个体面的名称的变量真正过分的要求?

体面的名字是指解释为什么我们跳过第一个元素的名字。不能简单地说“我们要跳过第一个元素”。1告诉我,这是自己的。


20
0和1不是幻数。
user949300

19
@ user949300哦,他们一定在这里。它们只是数字,有时并不神奇。仅仅因为2总是一个幻数并不意味着1永远不是一个幻数。魔术来自缺失的含义。从1个偏移量开始,到底意味着什么?在这里加0有什么好处?哦,是的,这些数字在这里肯定是神奇的。我可以看到小精灵的灰尘从他们身上掉下来。
candied_orange

4
当然,我将开始static final int LONELIEST_NUMBER = 1在所有Java代码中进行定义。:-)话虽如此,我想进一步想对您的答案进行表决,但除非您进行编辑,否则不可以。如此愚蠢的规则?
user949300

6
@Eiko:如果没有解释为什么循环从第二个元素开始,那么实际上可以保证某些维护程序员会将循环更改为从第一个元素开始。这就是为什么数字1在这种情况下是一个幻数。
Bart van Ingen Schenau '16

2
@BartvanIngenSchenau我以为在上下文中会有一个立即可见的原因。就像比较元素和它们的前任元素一样(我认为这是从1开始的最常见用例-我在这里看不到任何有用的常量名称)。如果第一个元素具有某些特殊含义,则可能会破坏设计,并且应该比命名该索引更好的修复方法。我并不是说从来没有理由在这里引入变量。只是我认为这些情况很少(也许应该是)。
Eiko

12

简短的回答:第一种选择更好。

第二种选择只会增加噪音。0 + 1不太可能帮助读者理解它本来可以是0,但实际上是1。很有可能他会在短时间内困惑并从循环的意义上分散注意力。尤其是在所有数组都从0开始的语言中。

如前所述,如果您想强调循环从1开始而不是从0开始的事实,只需添加一条注释即可。


10

不要告诉我们您跳过了第一项-我们可以看到这一点。不明显的是为什么。所以..如果从上下文来看不是很明显,请告诉我们原因:

// array[0] is just a header
for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

或者,如果您不喜欢评论,则类似于:

$lastHeaderIndex = 0;
for($i = $lastHeaderIndex + 1 ; $i < count(array) ; $i++){
    array[$i];
}

不要使用评论和欺骗手段来提醒我们该语言的工作原理。


6

您的示例看起来很虚构。在现实世界的代码中,循环需要从第二个数组元素开始的事实从以下代码行中很可能很明显。例如,如果实际代码如下所示

for($i=1 ; $i < count(array) ; $i++){
    array[$i-1]=array[$i];
}

无需解释或无需使用“ 0 + 1”结构即可清楚说明循环为什么从1开始而不是从0开始。

但是,如果循环内的代码没有以明显的方式解释原因(也许array[0]具有特殊含义,必须与其余元素区别对待),则添加解释性注释。但是在执行此操作之前,请三思而后行,是否可以避免具有array[0]这种特殊含义,并重新组织周围的代码,这可能是更好的选择。


在像您的示例代码这样的情况下,我喜欢将变量命名为“ oneBasedIndex”或“ zeroBasedIndex”。尽管针对该任务甚至更具体的方法会更好。
user949300

5

从未见过选项2,但我喜欢。为什么?使用选项1时,我想知道程序员是否忘记了数组从0开始。选项2更清楚地表明它们是故意从1开始的。

也就是说,无论哪种情况,最好都添加一条注释,以解释为什么要跳过元素。

或者,如果您可以轻松地描述为什么要从一个开始,请使用常量。例如,如果查看命令行参数,类似

define ('FIRST_REAL_ARGUMENT', 1);
for ($i=FIRST_REAL_ARGUMENT; ...)

就个人而言,我可能只使用评论,YMMV。


我要说的是,在您与初学者打交道的环境之外,我从未遇到过同事忘记数组从零开始的问题。如果您的工作还使用MATLAB之类的语言,我可以看到它正在发生,但是在大多数环境中,我假设程序员知道他们在做什么。哎呀,从1开始循环是很普通的事。跳过某些内容的第一个元素有很多原因。
Kat

@Kat对于将来的读者来说,原因很清楚。我宁愿假设将来的程序员都不知道自己在做什么。
A1rPun

2

我怀疑任何人都会被第一个混淆。我们都必须这样做。如此之多,以至于第二个混淆的可能性更大。“为什么那里有一个0+?它们是否以某种方式覆盖了+运算符?”

不错的编译器无论如何都会将第二个变成第一个,但是看起来您正在使用PHP(已解释)。因此,每次解释器遇到该循环时,实际上必须加0和1。这没什么大不了的,但是为什么要让解释器来做呢?


2

使用一个解释起点的变量。

您需要“ 跳过从零开始的数组中的第一个元素 ”,例如:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}

6
我喜欢使用变量,但我讨厌这个名字。它并不能解释为什么您要跳过第一个元素。无论如何,1告诉我。变量值更改时需要重命名的变量有什么用?我知道OP不知道为什么会这样,所以要选择一个好名字,您就必须弥补一个原因。如果没有更好的名字,我宁愿退回1。
candied_orange

@CandiedOrange我同意您的观点,变量名应该更有意义,但是出现的问题并不能解释为什么他要跳过第一个值。我的意思是,我仅举一个例子,作者可以选择最适合他的名字。
catta

请不要这样教。这很令人困惑。对于许多编码人员而言,他们将寻求最简单的名称,以便他们可以重新编写难以理解的代码。认真地说,我宁愿处理1而不是处理。
candied_orange

1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

如果一个对所有循环都从零开始的过程很着迷,则可以使用continue语句。添加注释,说明为什么要跳过,因为通常不会跳过。


2
这个选项的问题意味着我们将对每个元素进行评估,在循环中添加n个其他比较结果,同时简单地通过其他方法跳过第一个(移动数组,从i = 1开始,无论如何)表示仅做您需要做的工作。
凯文·费

3
@KevinFee如果您不处理大型数组,那么我想说这种比较并不是一个问题。我非常喜欢if first then skip带有露骨理由的评论的明确性。仍然没有上下文,所有解决方案都不是“最佳”
Ivan Pintar

-2

我要做的是在循环之前删除第一个元素。如果需要,请创建一个新数组。在评论中解释您为什么这样做。然后做一个简单的foreach。

$arrayCopy = $array; // in case you don't want to touch the original array
array_shift($arrayCopy); // removing first element because of X reason.
foreach($arrayCopy => $element) { 
    // do stuff
}

这样,您的意图就很清楚了。

为了进一步说明,您可以将代码包装在具有适当名称的方法中,以使事情更清楚。

function doStuffToAllButTheFirst($array) { // this copies the original array, so there are no sideffects
    array_shift($array);
    foreach($array => $element) { // do stuff }  
}

但是,所有这些仍然缺少上下文。您想对这些元素做什么?您将要返回新数组吗?您之后是否关心原始阵列和新阵列doStuff()

无论如何,这里没有明确的答案,而如何使代码可读则在很大程度上取决于上下文。


1
我之所以这样,是因为我现在不需要处理索引,这总是一个加号。
Tomas Zubiri

1
这里的缺点是,如果您不希望有副作用,则需要复制整个数组。
Tomas Zubiri

1
而如果我们从1开始的原因是因为我们在做$array[$i-1] = $array[$i]或类似的事情(按照@DocBrown的回答)怎么办?
凯文·费

1
这对我来说太可怕了。除了效率低下,副作用和无法解决常见用例外1(请参见Kevin Lee的评论),这根本无法使代码更加清晰。读者必须了解array_shift,其作用以及如何工作。也许这行代码是一个错误?它会修改数组还是返回一个新数组?它是插入元素还是删除元素?它会改变索引吗?我看不到使用基于一个的循环在该功能上不会有什么大的改进(并且赋予其名称,可以立即理解)。
Eiko

1
这些问题的答案高度依赖于上下文。至于效率,我会花一天的时间进行学习……在大多数情况下,任何性能差异都几乎看不到。
伊万·平塔尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.