我有一个功能' getMin'应该返回最小值。此功能使用另一个功能' urvalFun'为了确定这个最小值。以下是' urvalFun'
的演示get1:: (String,String,Double ) -> String
get1 (x,_,_ ) = x
get2 :: (String,String,Double)-> String
get2 (_,x,_) = x
get3:: (String,String,Double)->Double
get3 (_,_,x) = x
distDiff:: String-> String->[(String,String,Double)] ->Double
distDiff a b diMat = sum [z |(x,y,z)<- diMat, (x == a && y /= b)
|| (y == a && x /= b) ]
urvalFun:: Int -> (String,String,Double)->[(String,String,Double) ]->Double
urvalFun size triple diMat = ((fromIntegral size)-2)*(get3 triple)
- ( (distDiff (get1 triple) (get2 triple) diMat ) + (distDiff (get2 triple)
(get1 triple) diMat ))
没有必要理解这段代码,唯一重要的是如果我评估:
urvalFun 3 ("a","b",0.304) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
这将评估为-1.03999
urvalFun 3 ("a","d",0.52) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
这将评估为 - 0.60799
urvalFun 3 ("a","e",0.824) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
这将评估为1.1e ^ -16
现在我们知道用(&#34; a&#34;,&#34; b&#34;,0.304)和[(&#34; a&#34;,&#34; b&#34)调用urvalFun ;,0.304),(&#34; a&#34;,&#34; d&#34;,0.52),(&#34; a&#34;,&#34; e&#34;,0.824)]将得到最小的值。我想创建一个函数&#39; getMin&#39;它将返回此最小值(使用与上述示例中相同的向量作为参数),如上所示。问题是它不会工作我不知道为什么
getMin:: [(String,String,Double)]->Double
getMin diMat = inner 0 diMat 2000
where
inner 3 diMat min = min
inner n diMat min
|current > min = inner (n + 1) (diMatMinus ++ [(head diMat) ]) min
|otherwise = inner (n+1) (diMatMinus ++ [(head diMat) ]) current
current = urvalFun (length diMat) (head diMat) diMat
diMatMinus = tail diMat
尝试评估例如
getMin [("a","e",0.824),("a","d",0.52),("a","b",0.304)]
将评估为-1.1e ^ -16
这不是我想要的,因为我希望它返回-1.03999
有人可以帮助我吗?
(这段代码有点临时但是正在建设中,我现在正在做一些测试)
注意我已经重新排列了向量,以便三元组(&#34; a&#34;,&#34; b&#34;,0.304)是向量中的最后一个元素。
答案 0 :(得分:3)
首先,您需要一种方法来将最小元素传递给urvalFun
。这可以使用minimumBy
完成。
请注意以下内容
λ> let ls = [("a","d",0.52),("a","e",0.824),("a","b",0.304)]
λ> let min = minimumBy (\(_,_,c) (_,_,c') -> compare c c') ls
λ> urvalFun 3 min ls
-1.0399999999999998
或许这就是你想要的:
λ> minimum [ urvalFun 3 x ls | x <- ls]
-1.0399999999999998
如果你还想将n从0改为3或其他东西,那么可以进一步修改。我建议用英语说明你希望你的功能做什么。
答案 1 :(得分:1)
您希望在给定列表中找到最小化功能的值。
我将使用比您更简单的示例:找到最小长度的字符串。您可以通过替换length
函数来适应您的情况。
> import Data.Foldable
> let list = ["hello", "world!", "here", "is", "fine"]
> minimumBy (comparing length) list
"is"
上述方法有效,但每次执行比较时都会调用length
,即大约是列表长度的两倍。也可以避免这种情况,并且每个元素只使用length
一次,通过预先计算:
> snd $ minimumBy (comparing fst) [ (length x, x) | x <- list ]
我们首先将每个字符串与其长度配对,仅根据长度取最小长度字符串对,最后只取这个字符串中的字符串。
顺便说一句,我建议你避免使用get1
这样的函数来访问元组:它们在Haskell代码中不是惯用的,它通常利用模式匹配来获得相同的效果:例如
urvalFun:: Int -> (String,String,Double)->[(String,String,Double) ]->Double
urvalFun size (s1,s2,d) diMat =
(fromIntegral size - 2)*d - distDiff s1 s2 diMat + distDiff s2 s1 diMat
看起来更具可读性。
head,tail
也特别危险,因为它们是偏袒的:如果您在空列表中使用它们,它们会使程序崩溃,而不提供太多解释。
通常,使用列表,使用索引或计数器变量来计算列表的长度时,通常不需要而且不是惯用的。人们通常可以简单地使用模式匹配和递归,甚至是标准的折叠/贴图函数。
答案 2 :(得分:1)
请注意,对于大小为3的列表,您的getMin
函数可能会被写入:
getMin' [x,y,z]
= minimum [ urvalFun 3 x [x,y,z]
, urvalFun 3 y [y,z,x]
, urvalFun 3 z [z,x,y]
]
您可以使用zip和辅助函数为urvalFun
函数创建参数序列:
rotate (x:xs) = xs ++ [x]
zip "xyzw" (iterate rotate "xyzw")
= [ ('x', "xyzw"),
('y', "yzwx"),
('z', "zwxy"),
('w', "wxyz") ]
因此:
import Data.List
getMin tuples = minimum (zipWith go tuples (iterate rotate tuples))
where n = length tuples
go (x,xs) = urvalFun n x xs