获取最小值

时间:2016-07-28 07:31:22

标签: haskell vector

我有一个功能' 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)是向量中的最后一个元素。

3 个答案:

答案 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