def sorting(arr)
sorted = false
until sorted
sorted = true
arr.each_index do |i|
next if i == arr.length - 1
if arr[i] > arr[i + 1]
arr[i], arr[i+1] = arr[i+1], arr[i]
sorted = false
end
end
end
arr
end
p sorting([7, 4, 5, 2, 1, 3]) => [1, 2, 3, 4, 5, 7]
首先:当我们在sorted = true
循环内调用until
时,它满足已排序的条件,它应该结束循环。
第二:有人可以解释为什么迭代方法中next if
的过程不会继续迭代整个数组,
它应该在第一次迭代后结束,然后调用sorted = true
。
我被要求解释,我想知道是否有人能提供更好的解释。
谢谢Ruby Masters!
答案 0 :(得分:3)
首先,until
是一个顶级测试循环。在再次测试until
条件之前,整个块必须循环;它不会在循环中的每个语句之后进行测试。您必须在end
再次评估之前到达next
或until
。
其次,<statement> if <condition>
是if <condition> <statement> end
的红宝石简写。它允许您在一行上写一个简单的条件而不会牺牲可读性。 next
只会在arr.each_index
循环的最后一次迭代中执行,从堆栈上升到until
条件,此时sorted
将设置为{false
1}}。
要了解其工作原理,请尝试运行以下修改:
#!/usr/bin/ruby
def sorting(arr)
puts "starting with #{arr}"
sorted = false
until sorted
sorted = true
arr.each_index do |i|
if i == arr.length - 1
puts "'next' when i == #{i}, arr = #{arr}"
next
end
if arr[i] > arr[i + 1]
puts "swapping at #{i}: #{arr[i]} <=> #{arr[i+1]}"
arr[i], arr[i+1] = arr[i+1], arr[i]
sorted = false
end
end
end
arr
end
p sorting([7,4,5,1,2,3])
该程序的输出是:
starting with [7, 4, 5, 1, 2, 3]
swapping at 0: 7 <=> 4
swapping at 1: 7 <=> 5
swapping at 2: 7 <=> 1
swapping at 3: 7 <=> 2
swapping at 4: 7 <=> 3
'next' when i == 5, arr = [4, 5, 1, 2, 3, 7]
swapping at 1: 5 <=> 1
swapping at 2: 5 <=> 2
swapping at 3: 5 <=> 3
'next' when i == 5, arr = [4, 1, 2, 3, 5, 7]
swapping at 0: 4 <=> 1
swapping at 1: 4 <=> 2
swapping at 2: 4 <=> 3
'next' when i == 5, arr = [1, 2, 3, 4, 5, 7]
'next' when i == 5, arr = [1, 2, 3, 4, 5, 7]
[1, 2, 3, 4, 5, 7]
这当然是学术性的:对数组进行排序的正确方法是使用Array#sort。
注意:next
只是必需的,因为在each_index
循环的最后一次迭代中,i + 1
将超出数组的范围,这将导致下一行访问arr[i + 1]
失败(它将评估为nil
,并且您无法将整数与nil进行比较)。执行此操作的替代方法是修改交换测试索引周围的条件,或者将枚举数组的循环外部更改为更小的范围。
修改条件,消除next
,这是有效的,因为逻辑和条件从左到右进行计算,解释器在第一个为假时立即停止:
def sorting(arr)
sorted = false
until sorted
sorted = true
arr.each_index do |i|
if (i < arr.size - 1) && (arr[i] > arr[i + 1])
arr[i], arr[i+1] = arr[i+1], arr[i]
sorted = false
end
end
end
arr
end
p sorting([7,4,5,1,2,3])
更改循环的范围,这更好,因为循环执行次数较少:
def sorting(arr)
sorted = false
until sorted
sorted = true
(0..arr.size - 2).each do |i|
if (arr[i] > arr[i + 1])
arr[i], arr[i+1] = arr[i+1], arr[i]
sorted = false
end
end
end
arr
end
p sorting([7,4,5,1,2,3])
next
类似于其他语言中的goto
,如果可能,应该避免使用。