那么,有人可以解釋一下這是如何解決問題的嗎?
我不明白它是如何通過呼叫自身并重復 #array[0] 來獲得 #array.sum 的sum_array(array[1..-1])。我知道它會自行作業,直到array == 0,然后作業本身又回來了??
有人可以追蹤我扔的步驟嗎?
例子:
# sum_array([]) # => 0
# sum_array([5]) # => 5
# sum_array([5, 2]) # => 7
# sum_array([4, 10, -1, 2]) # => 15
#??################################??#
def sum_array(array)
return 0 if array.empty?
array[0] sum_array(array[1..-1])
end
#??###############################??#
uj5u.com熱心網友回復:
在 Ruby 中,除了第一個元素已從陣列中洗掉外,array[1..-1]其他相同。array
所以array[0] sum_array(array[1..-1])意味著“將第一個元素添加到除第一個元素之外的每個元素的總和”。如果您考慮一下,這相當于將陣列中的每個元素相加。(加法應該是associative,因此首先將陣列中的最后一個元素相加而不是從前兩個元素相加開始是有效的。)
你可以把它寫成這樣的數學方程:
(a b c d) = a (b c d) = a (b (c d))
如果您添加一些簡單的除錯命令,您可以自己跟蹤這些步驟:puts
def sum_array(array)
return 0 if array.empty?
puts "sum_array called with #{array.inspect}"
tail = sum_array(array[1..-1])
puts "sum_array returning #{array[0]} #{tail}"
array[0] tail
end
sum_array([2, 4, 7, 8])
uj5u.com熱心網友回復:
@David 的答案可以通過縮進分隔方法的各個實體來增強。在這里,從同一列開始的所有代碼都對應于該方法的同一實體。
INDENT = 6
$col = -INDENT
def indent; $col = INDENT; end
def undent; $col -= INDENT; end
def pu(s); puts "#{" "*$col}#{s}"; end
def puhline; pu('-'*(65-$col)); end
def sum_array(array)
indent
puhline
pu "sum_array called with argument array = #{array.inspect}"
if array.empty?
pu "returning 0 as array is empty"
puhline
undent
end
return 0 if array.empty?
pu "calling sum_array(#{array[1..-1].inspect})"
tail = sum_array(array[1..-1])
pu "sum_array returned tail = #{tail.inspect}"
pu "returning array[0] tail = #{array[0] tail}"
puhline
undent
array[0] tail
end
sum_array([2, 4, 7, 8])
#=> 21
顯示以下內容。
-----------------------------------------------------------------
sum_array called with argument array = [2, 4, 7, 8]
calling sum_array([4, 7, 8])
-----------------------------------------------------------
sum_array called with argument array = [4, 7, 8]
calling sum_array([7, 8])
-----------------------------------------------------
sum_array called with argument array = [7, 8]
calling sum_array([8])
-----------------------------------------------
sum_array called with argument array = [8]
calling sum_array([])
-----------------------------------------
sum_array called with argument array = []
returning 0 as array is empty
-----------------------------------------
sum_array returned tail = 0
returning array[0] tail = 8
-----------------------------------------------
sum_array returned tail = 8
returning array[0] tail = 15
-----------------------------------------------------
sum_array returned tail = 15
returning array[0] tail = 19
-----------------------------------------------------------
sum_array returned tail = 19
returning array[0] tail = 21
-----------------------------------------------------------------
uj5u.com熱心網友回復:
要了解遞回,首先必須了解遞回。開個玩笑,有點。我將給出與這里的答案略有不同的答案。
想象一下,我們用另一種語言表達了這一點,比如 Scheme/Lisp... 也想象一下我們有三個函式:
(null? a)它告訴我們陣列a是否為空/空。(car a)它回傳陣列的第一個元素a。(cdr a)它回傳陣列/串列的其余部分。- 哦,加法也很奇怪 ( 1 2) == 3
; If `a` is empty, the sum is 0.
; Otherwise, the sum is the first item plus
; the result of calling sum on the rest of the list.
(define (sum a)
(if (null? a)
0
( (car a) (sum (cdr a)))))
我們可以跟蹤呼叫(sum '(1 2 3 4)):
(sum '(1 2 3 4))
( 1 (sum '(2 3 4)))
( 1 ( 2 (sum '(3 4))))
( 1 ( 2 ( 3 (sum '(4)))))
( 1 ( 2 ( 3 ( 4 (sum '())))))
( 1 ( 2 ( 3 ( 4 0))))
( 1 ( 2 ( 3 4)))
( 1 ( 2 7))
( 1 9)
(10)
uj5u.com熱心網友回復:
我認為以理解數學中任何遞回定義的方式(例如著名的斐波那契數列)或歸納數學證明的方式來理解它是最容易理解的。
在那些你建立一個基本情況,然后有一個公式將更復雜的情況簡化為更簡單的情況。
例如,在斐波那契案例中,你會用數學寫出如下內容:
fib 0 = 0
fib 1 = 1
n>1 : fib n = fib(n-1) fib(n-2)
在您的總和示例中,您同樣會有
sum [] = 0
sum [x:xs] = x sum xs
您的代碼實際上是將這些數學公式直接翻譯成 Ruby。
話雖如此,您的功能將更慣用地表達為
def sum_array(array)
array.reduce(&: )
end
這是因為您的遞回模式非常普遍,以至于 Ruby 類Enumerable(Array 是其子類)包含reduce針對這種情況的通用方法。查看 Ruby 檔案以了解您還可以使用reduce.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/410169.html
標籤:
上一篇:ruby中陣列內哈希值的總和
下一篇:讓這些影像在Vue.js中呈現
