跳转至

应使用何种循环类型?

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/what-type-of-loop-should-i-use

84874 为本文评分:

3.2

应使用何种循环类型?

作者:匿名 日期:2016年2月18日,星期四

在我一月份撰写的一篇博客文章《为什么 IDL 中的 for 循环如此之慢?》中,我讨论了在 IDL 及其他编程语言中如何提高循环效率。该文章特指 For 循环,但其原则同样适用于 IDL 中任何类型的循环。这就引出了一个问题:在某些情况下,某些循环是否比其他循环更好?如果是,那么最好使用哪种循环?

事实上,解决问题的方法通常不止一种,几乎所有需要使用循环的编程问题都可以通过不止一种循环类型来解决。考虑到效率问题,每种循环类型都有其优缺点。

以下是每种循环类型的描述,以及一些优缺点和比较:

For 循环

For 循环可能是所有编程语言中最常见和最广为人知的循环类型。

For 循环可用于遍历数组元素:

For 循环也可用于执行固定次数的迭代:

默认情况下,增量为一。您还可以按给定的增量进行迭代,该增量指定为第三个参数。增量甚至可以为负值。

优点:

  • 在 For 循环中,迭代索引始终是一个明确定义的变量。按照惯例,该变量通常是字母 i。这使得通过该索引来访问一个或多个数组变得很容易。
  • 通过使用嵌套的 For 循环,可以轻松地遍历多维数组的元素。按照惯例,下一个循环将使用变量 j,然后是 k,依此类推。

缺点:

  • 要使用 For 循环,必须知道 For 循环遍历的数组的长度,或者必须知道迭代的总次数。在某些情况下,这两个确定值都未知。
  • 要在满足特定条件后跳出循环,您需要显式编写带有 BREAK 语句的条件语句。

效率:

鉴于您是在遍历一个已知长度的数组,或者知道迭代次数,那么向量化以及尽可能多地将操作和基于数组的条件判断移出循环是非常容易的。

Foreach 循环

与 For 循环类似,Foreach 循环用于遍历输入中的给定数量的项。

Foreach 循环有一个可选的索引参数,以备需要时使用。

优点:

  • Foreach 循环对程序员来说特别方便,因为在您不关心索引的情况下,您无需考虑索引。
  • Foreach 被特意设计为 IDL 中 LIST 的一个操作符。其用法与使用 foreach 遍历数组非常相似。

  • 更方便的是,Foreach 也被特意设计为 IDL 中 HASH 的一个操作符。每次迭代中的元素是给定元素的值。可选的第三个参数为您提供该元素的键。

如果您真的需要,可以遍历一个有序哈希,甚至可以定义自己的索引。

缺点:

  • 与 For 循环不同,Foreach 循环不能用于执行固定次数的迭代。
  • 与普通的 For 循环相比,使用 Foreach 循环可能会损失效率。

效率:Foreach 与 For 的比较

  • 一个非常简单的 For 循环,其中不对数组进行索引,或者循环执行固定次数的迭代,相对来说非常快。

% 耗时: 0.00099992752 秒。

  • 如果在 For 循环的每次迭代中都定义了包含给定索引处元素的变量,那么事实证明,使用一个简单的 Foreach 循环所花费的时间完全相同。这是因为 IDL 在内部对 Foreach 循环执行了完全相同的操作。

% 耗时: 0.0019998550 秒。 % 耗时: 0.0019998550 秒。

  • 但是请注意,如果您要在 foreach 语句中使用第三个参数,您将牺牲效率。除非您确实从其便利性中受益,否则您应该只使用普通的 For 循环。

% 耗时: 0.0030000210 秒。

  • 另一方面,因为 foreach 已被 IDL 开发者专门实现为针对列表和哈希的工具,所以对于这两种对象,foreach 比普通的 For 循环效率高得多。

While 循环

While 循环用于执行不定次数的迭代,只要某个条件保持为真。

优点:

  • 如果迭代次数事先未知,那么这就是 For 循环无法使用的情况。
  • While 循环非常简单。它不包含索引或定义的变量,因此当只需要一个循环来持续执行某个操作,直到满足(或不满足)某个期望条件时,它非常方便。

缺点:

  • 这里有一个重要的警告:使用 While 循环时,您需要确保条件最终会在某个时间点变为 false。如果条件始终为真,那么您将陷入无限循环。

  • While 循环在 IDL 中效率相当低(见下面的示例)。

效率:While 与 For 的比较

当遍历数组时,以下是 For 与 While 的比较:

使用 For 循环: % 耗时: 0.0010001659 秒。

使用 While 循环: % 耗时: 0.026000023 秒。

While 循环速度慢得多的主要原因是,while 循环在每次迭代后都会检查条件,所以如果您要编写这样的代码,直接使用 For 循环代替即可。

但是,如果您在 For 循环中执行一个或多个条件检查,而这些检查在使用 While 循环时可能不需要,那么您可以考虑使用 While 循环,并使用 ++ 运算符手动递增索引。

Repeat 循环

Repeat 循环与 While 循环非常相似,因为它执行不定次数的迭代。while 循环和 repeat 循环之间的区别在于:1.) Repeat 循环开始时不需要条件,2.) Repeat 循环持续迭代直到条件为 false,而 while 循环则相反。

优点:

  • 事实证明,Repeat 循环实际上比 While 循环效率更高,如下所示。
  • Repeat 循环的便利之处可能在于,在许多情况下,条件直到进入循环内部才已知甚至才被定义。因此,while 循环通常需要将条件设置为一个虚拟状态,该状态必须评估为真。

缺点:

  • 与 While 循环一样,也可能陷入无限循环,因此确保最终始终能够满足结束条件非常重要。
  • 如果循环开始前的条件确实重要(即,在特定条件下您希望完全跳过循环),那么 While 循环可能更方便。然而,解决这个问题的简单方法是将整个循环放入一个条件语句中。

效率:Repeat 与 While 的比较

使用 While 循环: *% 耗时: 0.026000023 秒。*

使用 Repeat 循环: % 耗时: 0.016000032 秒。

因此,在这个基本示例中,Repeat 循环是更好的选择。然而,如果您发现需要在循环内的某个位置放置条件检查,而通过使用另一种类型的条件循环可以避免这些检查,那么使用总条件检查次数更少的那种循环,您可能会获得更好的性能。

重要说明

IDL 是一种解释型语言,这意味着 IDL 的解释器会将用户编写的代码编译成机器语言。因此,本文描述的许多性能差异是基于 IDL 如何解释每行代码的。其他语言可能具有完全不同的行为,因此,在 IDL 中循环类型的最佳选择,在另一种语言中可能并非最佳。

总结

每种情况都不同,因此每次开始编写循环时,考虑哪种循环类型最好是很重要的。也许在某种情况下,您只想使用最方便的类型,但如果您正在处理大量数据,那么性能可能是至关重要的。

您选择哪种循环最终取决于您。请记住,因为每种情况都不同,所以在一种情况下有效的方法,在其他情况下可能并不总是最佳的。换句话说,这些想法只是一些经验法则,但希望它们能帮助您开始做出决定。

如果不确定在特定情况下哪种方法可能更快,请记住,您始终可以创建一个样本数据集,并使用 IDL 的 tictoc 例程来测量代码运行所需的时间。

使用来自不同数据集的波段进行彩色图像显示 通过使用 Jagwire 组织数据来节省时间和精力