Julia 循环逻辑(while,for),不同于判断逻辑,循环逻辑(Repeated Evaluation)会在条件满足的情况下,重复地运行一段代码以实现数据迭代处理等功能。
在实现循环逻辑时,我们在考虑什么情况下需要重复执行的同时,也需要考虑什么情况下不再循环。这是在开发中不能忽略的两个对偶问题。
Julia提供了while
与for
这两种循环结构的同时,还提供了break
与continue
两个关键字,以便对循环进行控制。通过设定与业务功能相关的控制变量,并结合这两个关键字,便可实现在特定情况下终止循环或继续循环。
while
基于关键字while
的循环结构同if结构类似,也需要将逻辑表达式作为判断条件,基本语法如下:
while条件表达式
# 语句块
end
只有在“条件表达式”为true时,while
内部的语句块才会执行。
在while内部的语句运行到end时,会再次返回对条件进行判断,如果为false,则忽略while内部的语句块,直接跳到end处执行其后的其他语句。
为了对while循环进行动态控制,一般其判断表达式中有控制变量,而且能在内部语句块进行更新,从而可以修改下次判断条件的逻辑结果。例如:
julia> i = 1; # 循环控制变量
julia> while i <= 5 # 循环条件
print(i, " ") # 处理过程
global i += 1 # 改变控制变量的值,其中的global关键字后文会介绍
end
1 2 3 4 5
若非如此,条件便始终不变,while就会变成死循环或无限循环。
当然,对于条件表达式结果恒定不变的无限循环,也可以在满足内部某条件时通过关键字break
打断循环过程。例如:
其中,虽然while的条件表达式始终为true,成为无限循环结构,但通过控制变量与break
的结合使用,可在需要时退出循环。此例实现了与上例相似的功能,只是结果略有不同,有兴趣的读者可以对比研究一下。
关键字break能够强制循环退出,但在多层嵌套的循环中只会影响其所处的那一层,不会波及外层或内层循环结构。例如:
julia> i=1; j=1;
julia> while j <= 4
while true
print(i, " ")
if i > 5 # 内层循环控制
break # 强制退出内层循环
end
global i += 1 # 修改内层循环的控制变量
end
global j += 1 # 修改外层循环的控制变量
global i = 1 # 重置内层循环的控制变量
println() # 换行打印
end
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
例中break导致内层while循环只执行到i=6时跳出,但外层由j控制的while循环并没有受到break的任何影响,顺利执行了4次。
同样用于循环控制的continue
关键字,功能不同于break,不是打断循环,而是让循环运行到其位置时停止执行后续语句,并立即跳转到条件表达式处重新判断,如果条件成立便会再次重入循环。例如:
其中,循环控制变量i以10为上界,只要小于10便会不断运行循环体内的语句;但在i小于5的情况下,不会执行continue之后的代码,所以打印出的结果都是不小于5的数值。
for
另外一种循环由关键字for
构建,与while
的用法有很大的不同。在for循环中,控制循环的不再是条件表达式,而是遍历型表达式。其基本表述结构为:
for遍历表达式
# 语句块
end
其中,“遍历表达式”需要可迭代数据结构的支持。
一般而言,在数集迭代时便会驱动循环体的语句块一次次地执行;而循环的次数便是数集中可遍历到的元素个数。同时,遍历表达式本身会提供循环变量,用于逐一提取数集中的元素值,以便循环内部进行相应的处理。
Julia中提供了三种基本的遍历表达方式,如下:
for循环变量 = 可迭代数据集
# 更多语句
end
for循环变量in可迭代数据集
# 更多语句
end
for循环变量 ∈ 可迭代数据集
# 更多语句
end
其中,三个遍历操作符=、in及∈是等价的,可以任选一个。
所谓可迭代数据集,主要是指后面介绍的元组(Tuple)、字典(Dict)及集合(Set),或者数组(Array)及范围表达式(Range)等。为了叙述方便,这里作简单的说明:元组的形式为(1,2,3),一旦创建内部元素不能再变更;数组是多维数据序列,以中括号表达,例如[1,2,3]或[1 2 3]便是有三个元素的数组;而范围表达式则用于表达等差序列,是一种迭代器,例如1:10表示公差为1的整数序列,取值1到10共计10个元素。
下面我们以实例来了解for循环的使用,例如:
julia> for i = 1:5
print(i, " ")
end
1 2 3 4 5
julia> for i in 1:5
print(i, " ")
end
1 2 3 4 5
julia> for i ∈ 1:5
print(i, " ")
end
1 2 3 4 5
或者:
julia> for i = [1 2 3 4 5]
print(i, " ")
end
1 2 3 4 5
julia> for i in [1 2 3 4 5]
print(i, " ")
end
1 2 3 4 5
julia> for i ∈ [1 2 3 4 5]
print(i, " ")
end
1 2 3 4 5
又或者:
julia> for i = (1,2,3,4,5)
print(i, " ")
end
1 2 3 4 5
julia> for i in (1,2,3,4,5)
print(i, " ")
end
1 2 3 4 5
julia> for i ∈ (1,2,3,4,5)
print(i, " ")
end
1 2 3 4 5
在for循环中,还支持同时对多个数据集进行遍历,例如:
而且遍历操作符也可以混用,例如:
在这种多遍历的表达中,得到的循环变量组合实际是每个数据集的笛卡尔积。也正因如此,遍历操作的顺序影响着内部语句中循环变量的取值。如果更换遍历操作的顺序,将会得到不同的结果。例如:
julia> for j = (1,2,3,4,5), i=1:2
print((i, j), " ")
end
(1, 1) (2, 1) (1, 2) (2, 2) (1, 3) (2, 3) (1, 4) (2, 4) (1, 5) (2, 5)
julia> for j in 3:4, i = [1 2 3 4 5]
print((i, j), " ")
end
(1, 3) (2, 3) (3, 3) (4, 3) (5, 3) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
可见与上述的运行结果不同。其中的i或j虽然仍出自同一数集,但因为遍历顺序的不同,循环变量的组合出现了差异。
还有一点需要注意,每一个遍历表达式之间的分割符是逗号而非是分号。如果使用分号,则会产生出乎意料的结果。例如:
julia> for i=1:2; j=3:4
print((i, j), " ")
end
(1, 3:4) (2, 3:4)
可见只执行了2次循环,而不是4次;而且j的值不再是元素,也没有实现笛卡尔积。这是因为i=1:2; j=3:4这种表达不再是遍历表达式,而是复合表达式。
当然,在for循环中,我们同样可以使用break
与continue
来控制循环的运行。例如:
julia> for i = 1:1000
print(i, " ")
if i >= 5
break
end
end
1 2 3 4 5
例中的i在遍历表达中可以取到1000个数值,但因内部的if语句要求i>=5
时break(中断循环),所以该循环只实际执行了5次。再例如:
julia> for i = 1:10
if i % 3 != 0
continue # 重新跳到for i = 1:10
end
println(i)
end
3
6
9
即只有在i是3的倍数的时候,才会将i的值打印出来。
另外,在for循环中,continue的运作与在while中的表现是相同的,也同样只会影响其所处的内层循环,不会波及外层循环。例如:
julia> for j = 1:5
println("\nloop ", j) # \n为换行符,便于查看结果
for i = 1:10
if i % 3 != 0
continue # 重新跳到for i = 1:10
end
print(i, " ")
end
end
loop 1
3 6 9
loop 2
3 6 9
loop 3
3 6 9
loop 4
3 6 9
loop 5
3 6 9
其中由j控制的外层循环完整地运行了5次,而由i控制的内层循环只在i为3的倍数时完整地运行了3次,但实际仍运行了10次。
酷客网相关文章:
评论前必须登录!
注册