编程语言学多了你会发现虽然每一门编程语言都有其各自的语法、特性,但它们都有着一些程序内秉的框架:数据类型、条件判断、循环,所以才有了那句言简意赅的定义:
程序 = 算法 + 数据结构
算法即步骤,但不是每一步都该执行,也不是重复的代码都需要拷贝。学习控制结构并正确地使用它是打到高端局的必经之途。
下面呈上 R 关于控制结构的知识,与君共享。
条件语句的一般形式:
if (condition) true_expression else false_expression
或者:
if (condition) expression
表达式并非总是被执行,所以 if
函数的类型是special:
> typeof(`if`)
[1] "special"
R 中,条件语句不是向量型运算。如果条件语句是由一个以上的逻辑值组成的向量,那么执行该语句时只会用到向量的第 1 个元素。例如:
> x <- 10
> y <- seq(6,17)
> if (x < y) x else y
[1] 6 7 8 9 10 11 12 13 14 15 16 17
Warning message:
In if (x < y) x else y : 条件的长度大于一,因此只能用其第一元素
如果我们想要执行向量化的运算,这时候可以采用 ifelse
函数:
> x <- 10
> y <- seq(6,17)
> ifelse(x<y, x, y)
[1] 6 7 8 9 10 10 10 10 10 10 10 10
如果要根据不同的单个输入返回不同的值,可以用下面的代码实现这个功能:
> switcheroo.if.then <- function(x){
+ if (x == "a")
+ "camel"
+ else if (x == "b")
+ "bear"
+ else if (x == "c")
+ "camel"
+ else
+ "moose"
+ }
上述代码本身略显冗长。接触过其他编程的朋友肯定接触过不少类 switch
或 case
的语句,R 也存在着switch
函数,所以我们可以用下面的语句实现该功能:
> switcheroo.switch <- function(x){
+ switch(x,
+ a="alligator",
+ b="bear",
+ c="camel",
+ "moose")
+ }
可以测试它们的结果
> switcheroo.if.then("a")
[1] "camel"
> switcheroo.if.then("f")
[1] "moose"
> switcheroo.switch("a")
[1] "alligator"
> switcheroo.switch("f")
[1] "moose"
R 中存在三种不同的循环结构。最简单的是 repeat
,它只是重复同一个表达式:
repeat expression
若要跳出循环,可以使用 break
命令。若要跳到循环的下一轮迭代,可以用 next
命令。
下面例子中输出所有不大于 25 的 5 的倍数:
> i <- 5
> repeat {if (i > 25) break else{print(i); i <- i + 5;}}
[1] 5
[1] 10
[1] 15
[1] 20
[1] 25
不过不使用 break
语句,命令将是一个死循环。
另外一个有用的循环结构是 while
,该结构在某个条件为真时,重复某个特定的表达式:
while (condition) expression
上个例子可以用 while
写出来:
> i <- 5
> while (i <= 25) {print(i); i <- i + 5}
[1] 5
[1] 10
[1] 15
[1] 20
[1] 25
同样地,我们可以在while循环中使用 break
与 next
命令。
最后一个是各种语言必然有的 for
循环,该结构遍历向量或列表中的每一个项目:
for (var in list) expression
同样我们用 for
循环来实现上面的例子:
> for (i in seq(from=5, to=25, by=5)) print(i)
[1] 5
[1] 10
[1] 15
[1] 20
[1] 25
初学者使用R的 for
循环需要注意:括号里有个 in
,我刚开始经常因为这个问题导致报错或者结果错误。
循环语句有两个需要记住的重要属性:
print
函数。var
变量在命令环境中是变化的。使用 R 的人是幸运的,向量化是 R 的内在特性之一,以至于我们常常忘记它的存在。
请珍惜这份开源的馈赠。