起初,我不知道Python的不夠好,但你打上了一個問題,「功能編程」,你說你想在一般的瞭解我想對你的問題給出一些一般的解釋。 首先,您應該重新思考map
和reduce
的操作以及他們的期望。我們從map
函數開始。
A map
函數列表(在函數式編程中,您不只有一個映射,每個泛型類型都有一個映射)對每個參數執行一個函數。該函數可以對單個參數進行操作並對其進行轉換。這一轉變的結果變成了新的清單。一個重要的注意事項是,您傳遞給map
的功能只能看到一個元素,因此您不能使用map
本身來整體轉換列表。你只能轉換列表中的每一個元素。但改變順序需要有一個列表中至少有兩個元素的想法,而一個地圖只能獲得一個元素。這就是反向邏輯不能在map
中並且必須是reduce
操作的一部分的原因。
另一方面,reduce
函數需要一個函數,它接受兩個相同類型的東西,並返回一個相同類型的單個項目。例如reduce函數可以採用「+」函數。 「+」是一個函數,它需要兩個int
並返回一個新的int
。簽名基本上是int + int = int
。減少的本質是把兩件事情變成一件新事物。例如,如果您的例子有類似「Foo」的更復雜的東西,那麼您必須提供的函數才能減少需要簽名Foo * Foo -> Foo
。意思是以Foo
作爲第一和第二個參數,並返回一個新的Foo
。
同樣重要的是要注意reduce
將如何與該功能的工作。讓我們假設你有上名列榜首[1,2,3,4,5]
讓我們假設你有一個accumulator function
帶兩個int
,只是將它們相加。你能想到會發生什麼是以下幾點。
- 的
reduce
函數採用列表的前兩個參數(1和2在這種情況下)
- 通行證那些在所述
accumulator function
(1 + 2 = 3)
- 並取代兩個參數列出結果。 [3,3,4,5]
- 回到1),並重復這一過程,直到你的名單隻有一個單一的項目
- 返回的是單個項目
所以你可以想像會發生什麼是以下
[1,2,3,4,5] -> 1 + 2 = 3
[3,3,4,5] -> 3 + 3 = 6
[6,4,5] -> 6 + 4 = 10
[10,5] -> 10 + 5 = 15
[15] -> Return just "15". Not a "[15]"
其實進程內部通常工作有點不同。但是這是你可以想象發生什麼的過程。請務必注意,您從不修改列表。你總是在那個過程中創建新的列表。另一個重要說明。在reduce
函數的末尾,您有一個單個項目的列表。但reduce
函數不會返回整個列表。它只返回單個元素。所以你得到15
和int
。您沒有得到包含15
的單個項目的列表。 Reduce將只返回那個單個元素。不管是什麼。另一種思考方式。你總是得到你的accumulator function
的類型。如果你傳遞一個accumulator function
採用兩個int
增加了他們,並返回一個新int
。您的減少功能也將返回一個int
。如果你傳遞一個accumulator function
,它有兩個Foo
類,並返回一個新Foo
。作爲結果,您的reduce
函數也將返回Foo
。 reduce
的退貨類型始終與您的accumulator function
的類型相同。
現在,讓我們所有的碎片,把它們放在一起。目標是扭轉一個列表。第一件重要的事情是。您的結果類型將是list
。這也意味着您傳遞到reduce
的功能也必須返回list
。但是由於輸入始終與輸出相同。您現在必須提供一個帶有兩個列表的accumulator function
,並返回一個新的列表。
但現在,讓我們退後一步。如果直接使用列表「[1,2,3,4,5]」作爲輸入來減少,會發生什麼?簡單的答案是,它不會起作用。 reduce
將採用您的列表的兩個參數。但是你有什麼是int列表。但你的accumulator function
期望兩個列表不是兩個int。爲了解決這個問題,你現在可以做的就是將列表中的每一個單元轉換成它自己的列表。那麼我們如何變換列表中的每一個元素呢?對!用map
!所以你必須做的是以下幾點。您首先將您的列表映射到列表的列表中。
[1,2,3,4,5] -> [[1],[2],[3],[4],[5]]
現在你的reduce函數得到你的第一個列表的前兩個元素。這意味着您現在有一個累加器函數,它獲取[1]
和[2]
作爲它的參數。兩個單獨的名單。但是你的累加器函數必須返回一個新的列表。如果不清楚,只是提醒累加器函數帶回的。
int, int -> int
float,float -> float
Foo,Foo -> Foo
list,list -> list
所以你現在要做的就是將這兩個列表合併成一個新的列表。換句話說,你必須追加/連接這兩個列表。我不知道你如何在Python中連接兩個列表讓我們假設這裏的操作是「++」。所以如果你僅僅連接第一個參數和第二個參數,你就不會得到你想要的。
[[1],[2],[3],[4],[5]] -> [1] ++ [2] = [1,2]
[[1,2],[3],[4],[5]] -> [1,2] ++ [3] = [1,2,3]
[[1,2,3],[4],[5]] -> [1,2,3] ++ [4] = [1,2,3,4]
[[1,2,3,4],[5]] -> [1,2,3,4] ++ [5] = [1,2,3,4,5]
[[1,2,3,4,5]] -> Return first element [1,2,3,4,5]
所以你要做的是將第二個參數連接到第一個參數。
[[1],[2],[3],[4],[5]] -> [2] ++ [1] = [2,1]
[[2,1],[3],[4],[5]] -> [3] ++ [2,1] = [3,2,1]
[[3,2,1],[4],[5]] -> [4] ++ [3,2,1] = [4,3,2,1]
[[4,3,2,1],[5]] -> [5] ++ [4,3,2,1] = [5,4,3,2,1]
[[5,4,3,2,1]] -> Return first element [5,4,3,2,1]
現在你得到的是你的反轉列表。所以你有什麼待辦事項
- 將每個元素映射到列表。所以,你得到的目錄列表
- 使用減少列表的每個列表Concat的到以相反的順序一個新的列表。
例如,在F#整個代碼是這樣的。
let list = [1;2;3;4;5]
let reversed =
list
|> List.map (fun x -> [x]) // map every element to a list
|> List.reduce (fun xs ys -> List.append ys xs) // Note ys ++ xs - reversed order for appending
printfn "%A" reversed
// prints: [5;4;3;2;1]
我想你應該可以把它翻譯成Python。作爲進一步通知。在函數式編程中,執行「映射」和「連續」操作(不反轉)也稱爲「綁定」。
您可能要重新考慮與'減少()'練了 - 它已經在Python 3 – TigerhawkT3
完全刪除@ TigerhawkT3不完全,但它仍然'functools'可用。 –
感謝您的信息。我會看看它的更多細節。還有什麼要知道上述代碼中的錯誤。 – s007