2016-07-28 9 views
0

Ich habe eine Funktion 'GetMin', die den Mindestwert zurückgeben sollte. Diese Funktion verwendet eine andere Funktion 'urvalFun', um diesen minimalen Wert zu bestimmen. Hier ist eine Demonstration von ‚urvalFun‘Erhalten Sie den Minimalwert

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)) 

Es ist nicht notwendig, diese chunck von Code zu verstehen, das einzige, was wichtig ist, ist, dass, wenn ich beurteilen:

urvalFun 3 ("a","b",0.304) [("a","b",0.304),("a","d",0.52),("a","e",0.824)] 

dies -1,03999 auswertet

urvalFun 3 ("a","d",0.52) [("a","b",0.304),("a","d",0.52),("a","e",0.824)] 

wird dies beurteilen zu - 0,60799

urvalFun 3 ("a","e",0.824) [("a","b",0.304),("a","d",0.52),("a","e",0.824)] 

wird dies zu 1.1e bewerten^-16

jetzt wissen wir, dass mit ("a", "b", 0.304) und [("a", "b", 0.304) Aufruf urvalFun, (“ a "," d ", 0.52), (" a "," e ", 0.824)] erhalten den kleinsten Wert. Ich möchte eine Funktion 'getMin' erstellen, die diesen minimalen Wert (mit dem gleichen Vektor wie in den obigen Beispielen als Parameter) zurückgibt, wie oben gezeigt. Das Problem ist, dass es nicht funktionieren wird ich keine Ahnung, warum

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 

Versuch zum Beispiel

getMin [("a","e",0.824),("a","d",0.52),("a","b",0.304)] 

der^-16

-1.1e evaluieren zu beurteilen, welche nicht will ich das, weil ich möchte, dass das zurückgeht -1.03999

Kann mir hier jemand helfen?

(dieser Code ist ein wenig hoc-Bit-Anzeige, aber es ist im Aufbau, ich bin jetzt einige Tests nur tun)

bemerken, dass ich den Vektor neu angeordnet haben, so dass die Tripel („a“, "b ", 0.304) ist das letzte Element im Vektor.

+0

Sie sagen, Sie den Minimalwert soll in die Liste aber '-1.03999' ist nirgends in der Liste. Vielleicht möchten Sie etwas wie ['MinimumBy'] (http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Foldable.html#v:minimumBy) – pdexter

+0

Sorry, der Header ist ein bisschen irreführend , Ich möchte nicht das Minimum aus einer Liste, ich möchte den minimalen Wert erhalten, der von urvalFun bestimmt wird, wie oben gezeigt –

+1

Sounds genau wie was 'minimumBy' tut, überprüfen Sie das. – pdexter

Antwort

3

Zuerst müssen Sie einen Weg finden, um das Mindestelement an urvalFun zu übergeben. Dies kann mit minimumBy erfolgen.

Beachten Sie die folgende

λ> 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 

Oder vielleicht ist das, was Sie wollten:

λ> minimum [ urvalFun 3 x ls | x <- ls]                                            
-1.0399999999999998 

Wenn Sie auch von 0 bis 3 oder etwas n wollen ändern, werden diese dann weiter modifiziert. Ich würde vorschlagen, auf Englisch zu sagen, was Sie Ihre Funktion tun möchten.

+0

das ist völlig falsch. Sie können nicht sagen, dass, wenn Sie die kleinste Zahl gefunden haben, in diesem Fall 0.304, dann bedeutet das nicht, dass 'urvalFun 2 ("a", "b", 0.304)' der kleinste Wert sein wird. In diesem Fall geschieht das nur, um zu korrigieren, aber nicht allgemein –

+2

Richtig, ich habe keine Ahnung, was Ihr Code tut, also habe ich eine beste Schätzung gemacht. Wenn Sie auf Englisch erklären können, was Sie wollen, kann Ihnen jemand besser helfen. Bitte sehen Sie sich meine Änderungen an, vielleicht versuchen Sie das. – pdexter

+0

ist es tatsächlich, was ich tun wollte - der "zweite Fall" in Ihrem Beitrag. –

1

Sie möchten den Wert in einer gegebenen Liste finden, der Ihre Funktion minimiert.

Ich werde mit einem einfacheren Beispiel als Ihnen arbeiten: Suche nach der Zeichenfolge mit Mindestlänge. Sie können dies an Ihren Fall anpassen, indem Sie die Funktion length ersetzen.

> import Data.Foldable 
> let list = ["hello", "world!", "here", "is", "fine"] 
> minimumBy (comparing length) list 
"is" 

Die oben genannten Arbeiten, aber es wird length jedes Mal einen Vergleich durchführt nennen, das heißt in etwa doppelt so groß wie Länge der Liste. Es ist auch möglich, dies zu vermeiden, und verwenden Sie length nur einmal pro Element, indem es precomputing:

> snd $ minimumBy (comparing fst) [ (length x, x) | x <- list ] 

Wir zunächst jede Saite mit seiner Länge koppeln, nehmen Sie das minimale Länge-Zeichenfolge Paar nach der Länge nur, und schließlich nehmen Sie nur die Zeichenfolge in einem solchen Paar.

By the way, würde ich empfehlen Sie Funktionen zu vermeiden, wie get1 Tupel zuzugreifen: sie in Haskell Code nicht idiomatischen sind, die in der Regel Muster für den gleichen Effekt passende ausnutzt: zum Beispiel

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 

Aussehen lesbarer.

head,tail sind auch besonders gefährlich, da sie teilweise sind: Sie werden Ihr Programm zum Absturz bringen, wenn Sie sie jemals auf einer leeren Liste verwenden, ohne viel Erklärung zu liefern.

Im Allgemeinen wird beim Arbeiten mit Listen die Verwendung von Indizes oder Zählervariablen zum Aufzählen bis zur Länge der Liste normalerweise nicht benötigt und ist nicht idiomatisch. Man kann oft einfach auf Mustervergleich und Rekursion oder sogar auf Standard-Falt-/Kartenfunktionen zurückgreifen.

1

Beachten Sie, dass für eine Liste der Größe 3 Ihre getMin Funktion geschrieben werden kann:

getMin' [x,y,z] 
    = minimum [ urvalFun 3 x [x,y,z] 
      , urvalFun 3 y [y,z,x] 
      , urvalFun 3 z [z,x,y] 
      ] 

Sie können die Reihenfolge der Argumente an die urvalFun Funktion mit Reißverschluss und und eine Hilfsfunktion erstellen:

rotate (x:xs) = xs ++ [x] 

zip "xyzw" (iterate rotate "xyzw") 
    = [ ('x', "xyzw"), 
     ('y', "yzwx"), 
     ('z', "zwxy"), 
     ('w', "wxyz") ] 

So:

import Data.List 

getMin tuples = minimum (zipWith go tuples (iterate rotate tuples)) 
    where n = length tuples 
     go (x,xs) = urvalFun n x xs