使用“注入",“除非"和“下一个"来确定最小值 [英] Using `inject`, `unless`, and `next` to determine the minimum value
问题描述
我有此代码:
def test(vertices, distances)
until vertices.empty?
nearest_vertex = vertices.inject do |a, b|
p "a = #{a}: b = #{b}"
p "distances[a] = #{distances[a]}, distances[b] = #{distances[b]}"
next b unless distances[a] #next b if distances[a] == true
next a unless distances[b] #next a if distances[b] == true
next a if distances[a] < distances[b]
p "b = #{b}"
b
end
p "nearest_vertex = #{nearest_vertex}"
vertices.delete nearest_vertex
end
end
vertices = [1, 2, 3, 4, 5, 6]
distances = {1 => 0, 2 => 3, 3 => 2, 4 => 18, 5 => nil, 6 => 7}
test(vertices, distances)
哪个输出:
"a = 1: b = 2"
"distances[a] = 0, distances[b] = 3"
"a = 1: b = 3"
"distances[a] = 0, distances[b] = 2"
...
"a = 1: b = 6"
"distances[a] = 0, distances[b] = 7"
"nearest_vertex = 1"
此处,未打印b = 6
.这是因为next
发出了停止迭代命令吗?
Here, b = 6
isn't printed. Is this because next
issues a stop iteration command?
"a = 2: b = 3"
"distances[a] = 3, distances[b] = 2"
"b = 3"
为什么迭代不继续在这里a=2: b=4
?
Why doesn't the iteration continue to a=2: b=4
here?
"a = 3: b = 4"
"distances[a] = 2, distances[b] = 18"
"a = 3: b = 5"
"distances[a] = 2, distances[b] = "
"a = 3: b = 6"
"distances[a] = 2, distances[b] = 7"
"nearest_vertex = 3"
...
一旦a
设置为3
,一切都会按我认为的方式工作.程序如何知道nearest_vertex
是三?
Once a
is set to 3
, everything works as I thought it should. How does the program know that nearest_vertex
is three?
在确定如何以及何时将顶点声明为nearest_vertex
时,我不理解inject
和next
之间的相互作用.没有比较运算符时如何比较距离?
I don't understand the interaction between inject
and next
in determining how and when to declare a vertex to be the nearest_vertex
. How are the distances compared when there is no comparison operator?
推荐答案
让我用纯Ruby解释Enumerable#inject
.请注意,以下代码Array
中对其进行解释,并重点介绍最基本的用法ary.inject(&block)
:
Let me explain Enumerable#inject
in pure Ruby. Note that the following code is NOT the original implementation of Enumerable#inject
. For clarity, I will explain it in class Array
, and focus on the most basic usage ary.inject(&block)
:
class Array
def inject(&block)
return nil if self.empty?
enumerator = self.each
accumulator = enumerator.next
loop do
begin
accumulator = block.call(accumulator, enumerator.next)
rescue StopIteration
break
end
end
accumulator
end
end
您可以看到在循环中,先前迭代的累加器和数组的当前元素被传递给块的参数,并且块的返回值被重新分配给累加器.
You can see that in the loop, the accumulator of previous iteration and the current element of the array is passed to the block's params, and the block's return value is reassigned to the accumulator.
那么什么是next x
块?
您可以将块视为一个匿名函数,而关键字next
是其return
.它将终止当前的块调用,并使该块返回x
(如果未显式指定返回值,则返回nil
).
You can think of a block as an anonymous function, and the keyword next
is its return
. It terminates the current block call and makes the block return x
(nil
if the return value is not explicitly specified).
顺便说一句,块中的break x
终止占用该块的方法调用,并使该方法返回x
.例如:
By the way, break x
in a block terminates the method call which takes the block, and makes the method return x
. For example:
[1, 2, 3, 4].inject do |acc, n|
break n if n == 2
acc + n
end
=> 2
当n
为2
时,Array#inject
由break
终止,并返回n
.
The Array#inject
is terminated by the break
when n
is 2
, and that n
is returned.
return
终止调用该块的方法的方法调用.例如:
return
in a block terminates the method call which calls the method that takes the block. For example:
def foo
[1, 2, 3].inject do |acc, n|
return n
end
puts 'You will never see this this sentence.'
end
foo
=> 2
并且没有打印句子,因为foo
以return
结尾.
And there is no sentence printed, because foo
is terminated by return
.
这篇关于使用“注入",“除非"和“下一个"来确定最小值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!