對映過濾並減少

標準庫中包含的兩個最基本的高階函式是 mapfilter。這些函式是通用的,可以在任何可迭代的函式上執行。特別是,它們非常適合在陣列上進行計算。

假設我們有一個學校資料集。每所學校都教授一門特定的科目,有多個類,每班平均學生人數。我們可以使用以下不可變型別為學校建模 :

immutable School
    subject::Symbol
    nclasses::Int
    nstudents::Int  # average no. of students per class
end

我們的學校資料集將是一個節目 3:

dataset = [School(:math, 3, 30), School(:math, 5, 20), School(:science, 10, 5)]

假設我們希望找到參加數學課程的學生總人數。為此,我們需要幾個步驟:

  • 我們必須將資料集縮小到只教數學的學校(filter
  • 我們必須計算每所學校的學生人數(map
  • 我們必須將學生人數列表減少到單一值,總和(reduce

一個天真的(不是最有效的)解決方案就是直接使用這三個高階函式。

function nmath(data)
    maths = filter(x -> x.subject === :math, data)
    students = map(x -> x.nclasses * x.nstudents, maths)
    reduce(+, 0, students)
end

我們在資料集中驗證了 190 名數學學生:

julia> nmath(dataset)
190

存在用於組合這些功能並因此改善效能的功能。例如,我們可以使用 mapreduce 函式一步執行對映和縮減,這樣可以節省時間和記憶體。

reduce 僅對+關聯操作有意義,但偶爾使用非關聯操作執行縮減也很有用。提供高階函式 foldlfoldr 以強制執行特定的減少順序。