如果你正在编写一个简单的小循环,你应该给计数器起什么名字?
提供示例循环!
我总是使用一个有意义的名称,除非它是一个单级循环并且变量除了“我已经通过这个循环的次数”之外没有任何意义,在这种情况下我使用i
.
使用有意义的名称时:
使用单个字母在此嵌套循环中查找错误可能很棘手:
int values[MAX_ROWS][MAX_COLS];
int sum_of_all_values()
{
int i, j, total;
total = 0;
for (i = 0; i < MAX_COLS; i++)
for (j = 0; j < MAX_ROWS; j++)
total += values[i][j];
return total;
}
而使用有意义的名称时更容易:
int values[MAX_ROWS][MAX_COLS];
int sum_of_all_values()
{
int row_num, col_num, total;
total = 0;
for (row_num = 0; row_num < MAX_COLS; row_num++)
for (col_num = 0; col_num < MAX_ROWS; col_num++)
total += values[row_num][col_num];
return total;
}
row_num
?- 被拒绝的替代品针对其他一些答案和评论,这些是使用的一些替代建议row_num
以及col_num
我选择不使用它们的原因:
r
and c
:这比i
and略好j
。如果我的组织的标准是单字母变量是整数,并且始终是等效描述性名称的第一个字母,我只会考虑使用它们。如果函数中有两个名称以“r”开头的变量,系统就会崩溃,即使代码中的任何位置出现其他以“r”开头的对象,可读性也会受到影响。rr
and cc
:这对我来说看起来很奇怪,但我不习惯双字母循环变量样式。r
如果它是我组织中的标准,那么我想它会比和稍好一些c
。row
and col
:乍一看,这似乎比row_num
and更简洁col_num
,并且具有描述性。但是,我希望像“行”和“列”这样的裸名词指代结构、对象或指向这些的指针。如果row
可能表示行结构本身或行号,则会导致混淆。iRow
and iCol
:这传达了额外的信息,因为i
它可能意味着它是一个循环计数器 whileRow
并Col
告诉你它在计数什么。但是,我更喜欢能够几乎用英文阅读代码:
row_num < MAX_COLS
读作“行号小于最大列数” ;iRow < MAX_COLS
充其量读作“该行的整数循环计数器小于最大(数量)列” 。row_num
我会接受的另一种选择是row_idx
:“索引”一词唯一地指的是数组位置,除非应用程序的域在数据库引擎设计、金融市场或类似领域。
我上面的示例尽可能小,因此有些人可能看不到描述性命名变量的意义,因为他们可以一次将整个函数放在脑海中。然而,在实际代码中,函数会更大,逻辑也更复杂,因此体面的名称对于提高可读性和避免错误变得更加重要。
总之,我对所有变量命名(不仅仅是循环)的目标是完全明确。如果有人阅读了我的代码的任何部分并且无法立即计算出变量的用途,那么我就失败了。
1) 对于普通的旧式小循环 - i, j, k - 如果您需要 3 级以上的嵌套循环,这意味着要么算法非常具体和复杂,要么您应该考虑重构代码。
Java 示例:
for(int i = 0; i < ElementsList.size(); i++) {
Element element = ElementsList.get(i);
someProcessing(element);
....
}
2)对于新风格的java循环for(Element element: ElementsList)
,最好使用普通的有意义的名字
Java 示例:
for(Element element: ElementsList) {
someProcessing(element);
....
}
3)如果可以使用您使用的语言,请将循环转换为使用迭代器
Java 迭代器示例:单击此处
我的经验是大多数人使用单个字母,例如:
i
,
j
,
k
, ... or
x
,
y
, or
r
,
c
(for row/column) or
w
,
h
(for width/height) 等。
但是我很久以前就学会了一个很好的替代方法,并且从那时起就一直在使用它:双字母变量。
// recommended style ● // "typical" single-letter style
●
for (ii=0; ii<10; ++ii) { ● for (i=0; i<10; ++i) {
for (jj=0; jj<10; ++jj) { ● for (j=0; j<10; ++j) {
mm[ii][jj] = ii * jj; ● m[i][j] = i * j;
} ● }
} ● }
如果好处不是立即显而易见:通过代码搜索任何单个字母会发现许多不是您想要的东西。该字母i
经常出现在不是您要查找的变量的代码中。
非嵌套循环: . . . 索引是一个值。
. . . 就像在代数中一样,使用 是最常见的做法 。. .
i
for (int i = 0; i < LOOP_LENGTH; i++) {
// LOOP_BODY
}
嵌套循环: . . . 区分指数有助于理解。
. . . 使用描述性后缀. . .
for (int iRow = 0; iRow < ROWS; iRow++) {
for (int iColumn = 0; iColumn < COLUMNS; iColumn++) {
// LOOP_BODY
}
}
foreach
循环:。. . 需要一个Object
名字。
. . . 使用描述性名称。. .
for (Object something : somethings) {
// LOOP_BODY
}
for
循环:。. . 迭代器引用对象。Iterator 两者都不是;一个索引,也不是一个索引。
. . .
iter
缩写 Iterators 目的。. .
for (Iterator iter = collection.iterator(); iter.hasNext(); /* N/A */) {
Object object = iter.next();
// LOOP_BODY
}
while
循环:。. . 限制迭代器的范围。
. . . 评论循环的目的。. .
/* LOOP_DESCRIPTION */ {
Iterator iter = collection.iterator();
while (iter.hasNext()) {
// LOOP_BODY
}
}
最后一个例子读起来很糟糕,没有评论,从而鼓励他们。 它可能很冗长,但在 C 中的范围限制循环中很有用。
始终尝试将变量命名为有意义且符合上下文的名称。
如果你不能决定,那么使用“索引”,如果只是为了让其他人(也许是你!)可以更容易地点击它以便以后重构。
Paul Stephenson请参阅此答案以获取示例。
我使用i、j、k(或r & c用于行列循环)。如果您在一个方法中需要三个以上的循环变量,则该方法可能太长且太复杂,您的代码可能会受益于将方法拆分为更多方法并正确命名它们。
i
如果我有一个嵌套循环,那么也是j
。
这种约定非常普遍,以至于如果您设法i
在一段代码中遇到一个看不到开头的变量,您仍然可以立即识别出它是什么。
I use i, ii, iii, iv, v ... Never got higher than iii, though.
仅当循环计数器是索引时,我才使用单个字母。我喜欢双字母背后的想法,但它使代码非常难以阅读。
如果要将计数器用作容器的索引,我使用i
, j
, k
。
如果要使用它来迭代一个范围(或执行一定数量的迭代),我经常使用n
. 不过,如果需要嵌套,我通常会恢复为i
, j
, k
.
在提供foreach
-style 结构的语言中,我通常这样写:
foreach widget in widgets do
foo(widget)
end
我想有些人会因为与 的命名widget
如此相似而拒绝widgets
我,但我觉得它很可读。
和之前的海报一样,我也使用 ii、jj、.. 主要是因为在许多字体中,单个 i 看起来与 1 非常相似。
我长期使用 i/j/k 命名方案。但最近我开始采用一种更随性的命名方法。
我已经按其含义命名了所有变量,那么为什么不以相同的确定性方式命名循环变量。
根据要求举几个例子:
如果您需要循环遍历项目集合。
for (int currentItemIndex = 0; currentItemIndex < list.Length; currentItemIndex++)
{
...
}
但我尽量避免正常的 for 循环,因为我倾向于想要列表中的真实项目并使用它,而不是列表中的实际位置。所以不要用 a 开始 for 块:
Item currentItem = list[currentItemIndex];
我尝试使用该语言的 foreach 结构。这改变了。
for (int currentItemIndex = 0; currentItemIndex < list.Length; currentItemIndex++)
{
Item currentItem = list[currentItemIndex];
...
}
进入
foreach (Item currentItem in list)
{
...
}
这使得它更容易阅读,因为只表达了代码的真正含义(处理列表中的项目)而不是我们想要处理项目的方式(保持当前项目的索引并增加它直到它达到长度列表的结束,因此意味着项目集合的结束)。
我仍然使用一个字母变量的唯一一次是当我循环槽尺寸时。但随后我会使用 x、y,有时还会使用 z。
我也使用双字母约定。二、jj、kk。您可以 grep 那些而不想出一堆不需要的匹配项。
我认为使用这些字母,即使它们加倍,是最好的方法。这是一个熟悉的约定,即使是加倍。
坚持惯例有很多话要说。它使事情更具可读性。
在 Perl 中,内部循环的标准变量名是$_。for、foreach和while语句默认使用此变量,因此您无需声明它。通常,$_可以像中性通用代词“它”一样阅读。所以一个相当标准的循环可能看起来像:
foreach (@item){
$item_count{$_}++;
}
在英语中,这翻译为:
对于每个项目,增加它的 item_count。
然而,更常见的是根本不使用变量。许多 Perl 函数和运算符默认为$_:
for (@item){
print;
}
用英语讲:
对于 [每个] 项目,打印 [it]。
这也是计数器的标准。(但计数器在 Perl 中的使用频率远低于在其他语言中,例如 C)。所以要打印从 1 到 100 的整数的平方:
for (1..100){
print "$_*$_\n";
}
由于只有一个循环可以使用$_变量,因此通常在最内层循环中使用它。这种用法与英语通常的工作方式相匹配:
对于每辆车,查看每个轮胎并检查其压力。
在 Perl 中:
foreach $car (@cars){
for (@{$car->{tires}}){
check_pressure($_);
}
}
如上所述,最好在外部循环中使用更长的描述性名称,因为在很长的代码块中很难记住通用循环变量名称的真正含义。
有时,使用较短的、非描述性的通用名称(例如$i、$j和$k)而不是$_或描述性名称是有意义的。例如,匹配已发布算法中使用的变量(例如叉积)很有用。
@JustMike。. . 几个例子: . . . 陪伴 Java 的。
非嵌套循环:。. . 尽可能限制范围
/*LOOP_DESCRIPTION*/ {
int i;
for (i = 0; i < LOOP_LENGTH; i++) {
// loop body
}
}
嵌套循环:。. . 同上
/*LOOP_DESCRIPTION*/ {
int row, column;
for (row = 0; row < ROWS; row++) {
for (column = 0; column < COLUMNS; column++) {
// loop body
}
}
}
这种布局的一个好处是它在没有评论的情况下读起来很糟糕,从而鼓励他们。
这可能很冗长,但就我个人而言,这就是我在 C 中执行循环的方式。
另外:我开始时确实使用了“index”和“idx”,但这通常被我的同龄人改为“i”。
第一条规则是变量名的长度应该与变量的范围相匹配。第二条规则是有意义的名称使错误更浅。第三条规则是,如果您想为变量名添加注释,那么您选择了错误的变量名。最后的规则是像你的队友那样做,只要它不抵消之前的规则。
我使用“counter”或“loop”作为变量名。现代 IDE 通常使用完成这个词,因此较长的变量名使用起来不会那么乏味。此外,将变量命名为它的功能可以让将要维护您的代码的程序员清楚地了解您的意图。
无论您选择什么,在您的代码中始终使用相同的索引,只要它具有相同的含义。例如,要遍历一个数组,您可以使用i
, jj
, kappa
, 等等,但始终在任何地方都以相同的方式进行:
for (i = 0; i < count; i++) ...
最佳实践是使循环的这一部分在整个代码中看起来相同(包括始终count
用作限制),这样它就成为一种习惯用法,您可以在精神上跳过它以便专注于代码的实质,循环体。
同样,例如,如果您正在遍历一个二维像素数组,您可能会写
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
...
只需在您编写此类循环的每个地方都以相同的方式进行。
您希望您的读者能够忽略无聊的设置并看到您在实际循环中所做的事情的精彩。
像往常一样, Steve McConnell 的Code Complete在这方面有一些很好的建议。相关页面(无论如何在第一版中)是 340 和 341。绝对建议任何有兴趣改进循环编码的人看看这个。McConnell 建议使用有意义的循环计数器名称,但人们应该阅读他自己要说的内容,而不是依赖我的薄弱总结。
在 Python 中,如果我只计算次数,我会使用 i、j 和 k。如果将迭代计数用作索引,我将使用 x、y 和 z。但是,如果我实际上是在生成一系列参数,我将使用一个有意义的名称。
如果它是一个简单的计数器,我坚持使用“i”,否则,使用表示上下文的名称。我倾向于将可变长度保持为 4。这主要是从代码阅读的角度来看,写入不算数,因为我们有自动完成功能。
我最喜欢在类矩阵集合上循环的约定是使用 x+y,因为它们在笛卡尔坐标中使用:
for x in width:
for y in height:
do_something_interesting(x,y)
对于整数,我使用 int index,除非它是嵌套的,否则我会在迭代的内容上使用 Index 后缀,例如 int groupIndex 和 int userIndex。
我已经开始使用与上下文相关的循环变量名称与匈牙利语混合。
循环遍历行时,我将使用iRow
. 循环遍历列时,我将使用iCol
. 当循环通过汽车时,我会使用iCar
. 你明白了。
我通常使用:
for(lcObject = 0; lcObject < Collection.length(); lcObject++)
{
//do stuff
}
对于数值计算、matlab 等,不要使用 i, j
这些是保留常量,但 matlab 不会抱怨。
我个人的最爱是
索引第一,第二计数器计数
我已经开始在 php 中使用 perlisms。
如果它是一个单一的迭代,$_
对于那些知道它的用途的人来说是一个好名字。
我的习惯是使用 't' - 接近 'r' 所以在输入 'for' 后很容易理解