學習軌道
/
jq
jq
/
練習
/
遞迴函式
遞迴函式

遞迴函式

學習練習

簡介

遞迴

遞迴函式是一種會呼叫自己的函式。

一個_遞迴函式_至少需要一個_基本情況_,以及至少一個_遞迴情況_。

基本情況會回傳一個值,而不會再次呼叫函式。 遞迴情況會再次呼叫函式,並修改輸入,讓它在某個時間點符合基本情況。

以下是一個計算陣列元素數量的範例。

def count:
  if length == 0 then
    0                       # base case
  else
    1 + (.[1:] | count)     # recursive case
  end;

([] | count),           # => 0
([11, 22, 33] | count)  # => 3

一個_遞迴函式_可以有很多個_基本情況_,也可以有很多個_遞迴情況_。 例如費波那契數列就是一個有兩個_基本情況_的遞迴數列。

def fibonacci:
  if . == 0 then
    0
  elif . == 1 then
    1
  else
    (. - 1 | fibonacci) + (. - 2 | fibonacci)
  end;

10 | fibonacci          # => 55

計算某個給定的值x在陣列中出現的次數,會有兩個_遞迴情況_。

def count_occurrences(x):
  if length == 0 then
    0
  elif first == x then
    1 + (.[1:] | count_occurrences(x))
  else
    (.[1:] | count_occurrences(x))
  end;

[11, 22, 33, 22, 44] | count_occurrences(22)    # => 2

實務上,走訪陣列和其他可列舉的資料結構時,最常使用內建函式,例如map和reduce,或是像[.[] | select(...)]這樣使用資料流。 在底層,有些內建函式則是用遞迴實作的。

說明

你剛加入一個維護 jq 資料管線的團隊。 在第一次結對工作時,你的新同事好奇地問: 「你知道 add、reverse 和 map 在底層是怎麼運作的嗎?一起來探索吧,試著用遞迴自己實作它們,不要用內建功能。」

1. 實作一個將陣列中數字相加的函式

我們要重新實作內建的 add 篩選器,藉此練習遞迴。 基本情況 是空陣列的總和為 0。

請用遞迴函式自己實作,不要使用內建的 add。

[5, 4, 6, 10] | array_add     # => 25

2. 反轉陣列

我們要重新實作內建的 reverse 篩選器。 基本情況 是空陣列反轉後仍是空陣列。

請用遞迴函式自己實作,不要使用內建的 reverse。

[5, 4, 6, 10] | array_reverse   # => [10, 6, 4, 5]

3. 映射陣列

我們要重新實作內建的 map 篩選器。 這個函式接受一個篩選器作為參數,對輸入陣列的每個元素執行該篩選器,並將輸出結果放在新的陣列中回傳。 基本情況 是空陣列映射後仍是空陣列。

請用遞迴函式自己實作,不要使用內建的 map。

[5, 4, 6, 10] | array_map(. + 10)   # => [15, 14, 16, 20]
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
jq Exercism

準備好開始 遞迴函式 了嗎?

註冊 Exercism,透過 12 個概念75 個練習 和真人引導來學習並精通 jq,全部免費。