我正在尝试将其转换为Haskell,
def longest_path(edge, edges):
remaining = list(edges)
del remaining[remaining.index(edge)]
possibles = [x for x in remaining if x[0] == edge[1]]
maxchain = []
for c in possibles:
l = longest_path(c, remaining)
if len(l) > len(maxchain):
maxchain = l
return [edge] + maxchain
据我所知,
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (x:xs)
| i == 0 = xs
| otherwise = x : deleteN (i-1) xs
longestPath edge edges = let
remaining = deleteN (fromMaybe $ elemIndex edge edges) edges
possibiles = [opt | opt <- remaining, (fst opt) == (snd edge)]
我无法弄清楚如何使用递归来执行for循环。有人有想法吗?
答案 0 :(得分:4)
注意:这个答案写在有文化的Haskell中。将其保存为*.lhs
并将其加载到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代码中做了什么?显然,我们从边缘列表中删除了当前的edge
:
remaining = list(edges)
del remaining[remaining.index(edge)]
幸运的是,有一个函数可以删除列表中元素的第一个出现位置,即delete
:
> let remaining = delete edge edges
到目前为止一切顺利。现在,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
答案 1 :(得分:3)
那个python代码并不是最好的......我没有看到找到edge
的索引,然后del
找到它...只是使用edges.remove(edge)
。
在Haskell中以同样的方式,您只需filter
边缘:
remaining = filter (/= edge) edges
现在,您的for
循环正在跟踪目前为止的最佳结果。 Haskell中的这个可以通过使用累加器参数的递归函数来完成。但是,此处的模式是fold
:
foldr f [] possibilities
其中:
f c maxchain = let l = longestPath c remaining
in
if length l > length maxchain then l else maxchain
您可以修改longestPath
以返回路径的长度,并避免调用length
...
完整的代码如下:
longestPath edge edges = foldr f [] possibilities
where
remaining = filter (/= edge) edges
possibilities = [opt | opt <- remaining, (fst opt) == (snd edge)]
f c maxchain = if length l > length maxchain then l else maxchain
where
l = longestPath c remaining
正如评论中指出的那样,filter
代替delete edge edges
,您可以使用edge
删除一个出现的<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="CalimplService" targetNamespace="http://webservice.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://webservice.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="com.webservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace="com.webservice" location="Ical.wsdl">
</wsdl:import>
<wsdl:binding name="CalimplServiceSoapBinding" type="ns1:Ical">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="rech">
<soap:operation soapAction="urn:Rech" style="document"/>
<wsdl:input name="rech">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="rechResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CalimplService">
<wsdl:port name="CalimplPort" binding="tns:CalimplServiceSoapBinding">
<soap:address location="http://localhost:8080/Calcu/services/CalimplPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
。但是,如果你正在处理标准图表,这不重要。