注意:這個答案寫在文學Haskell。將其保存爲3210並將其加載到GHCi中。
> import Data.Ord (comparing)
> import Data.List (delete, maximumBy)
> type Edge = (Int, Int)
讓我們來看看你的Python代碼,並認爲Haskell的功能應該如何看起來像:
def longest_path(edge, edges):
還好吧。我們從一個邊和一個邊的列表開始。因此,我們應該編寫一個這樣的函數:
> longestPath :: Edge -> [Edge] -> [Edge]
> longestPath edge edges =
現在,我們在我們的Python代碼中做什麼?
remaining = list(edges)
del remaining[remaining.index(edge)]
幸運的是,刪除元素第一次出現在列表中,即delete
功能:
> let remaining = delete edge edges
所以很顯然,我們從邊緣的列表中刪除我們目前edge
非常好。現在,possibles
只是用正確的終點邊緣的名單:
possibles = [x for x in remaining if x[0] == edge[1]]
那是太容易了:
> possibles = filter (edge `connectedTo`) edges
然後我們尋找所有可能的邊緣鏈最長。
maxchain = []
for c in possibles:
l = longest_path(c, remaining)
if len(l) > len(maxchain):
maxchain = l
既然我們不能在Haskell修改maxchain
,讓我們創建所有的中間路徑來代替:
> paths = [] : map (\e -> longestPath e remaining) possibles
這就是遞歸發生。對於我們可能的邊緣中的每個Edge
,我們創建該邊緣的longestPath
和其餘邊緣。
for
環的大部分可以表示爲map
和以下的摺疊。我們將使用摺疊是maximumBy
,在這裏我們通過它們的長度與comparing length
比較列表:雖然
> in edge : maximumBy (comparing length) paths
我們已經使用了一個小幫手,connectedTo
。但是,這很簡單:
> connectedTo :: Edge -> Edge -> Bool
> connectedTo (_,b) (x,_) = b == x
所有代碼一次:
import Data.List (delete, maximumBy)
import Data.Ord (comparing)
type Edge = (Int, Int)
longestPath :: Edge -> [Edge] -> [Edge]
longestPath edge edges =
let remaining = delete edge edges
possibles = filter (edge `connectedTo`) edges
paths = [] : map (\e -> longestPath e remaining) possibles
in edge : maximumBy (comparing length) paths
connectedTo :: Edge -> Edge -> Bool
connectedTo (_,b) (x,_) = b == x
你不需要外在的循環或遞歸。 「爲列表中的每個元素計算一些東西」,這裏有一個名爲'map'的內置函數。「查看列表並根據前一個值和當前列表元素更新一個值」另一個內置的foldr。 –
@nm這個'for'不是'map',因爲它在循環中跟蹤最好的'maxchain' ......它更像是一個'fold'。 – Bakuriu