2016-11-04 3 views
1

Ich neu bei Scala. Als Übung versuche ich eine Spielanweisung über eine Liste von Tupeln mit Wachen zu schreiben. Mir ist bewusst, dass eine Karte das Problem lösen würde, aber ich versuche, Verständnis für den Mustervergleich zu bekommen.Scala Matching Liste der Tupel mit Wachen

Ich möchte eine Funktion schreiben, die ein List[(Char, Int)] als Argument verwendet. Die Funktion sortiert die Einträge und wenn zwei Einträge denselben Schlüsselwert haben, werden sie addiert. Also würde das folgende Argument List(('q', 1'), ('a', 1), ('c', 2), ('a', 2), ('c', 1))List(('a', 3), ('c', 3'), ('q', 1)) werden.

Ich komme mit dem folgenden Code:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = { 
    chars match { 
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 > charP2) => 
     sortAndAggregateList((charP2, numP2) :: (charP1, numP1) :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 < charP2) => 
     sortAndAggregateList((charP1, numP1) :: (charP2, numP2) :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: (x : List[(String, Int)]) if (charP1 == charP2) => 
     sortAndAggregateList((charP1, numP1 + numP2) :: x) 
    case Nil => 
     Nil 
    } 
} 

Aber ich bekomme die folgende Warnung:

: 14: Warnung: fruchtlos Typprüfung: einen Wert vom Typ List [(Char, Int)] kann nicht auch eine List [(String, Int)] sein (das Underlying von List [(String, Int)]) (aber immer noch mit seinem Löschen übereinstimmen)

Ich habe versucht, die Liste fallen zu lassen, aber wenn ich das tue, bekomme ich eine Fehler, dass x vom Typ Any ist.

Irgendwelche Vorschläge?

+0

die Fehlermeldung angezeigt: Sie passen gegen 'chars', die eine' Listen Sie [(Char, Int)] 'auf, aber in dem Muster erwarten Sie, dass' x' eine 'List [(String, Int)]' ist. – Josef

Antwort

2

Der Fehler ist Ihre Typüberprüfung, die Sie nach jeder case-Anweisung durchführen (: List [(String, Int)]).

Wenn Sie Ihren Code auf die folgenden Fehler ändern verschwindet:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = { 
    chars match { 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 > charP2) => 
     sortList(p1 :: p2 :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 < charP2) => 
     sortList(p2 :: p1 :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 == charP2) => 
     val p3: (Char, Int) = (charP1, numP1 + numP2) 
     sortList(p3 :: x) 
    case x => 
     x 
    case Nil => 
     Nil 
    } 
} 

Danach werden Sie herausfinden, dass der Compiler Sie, dass P1 und P2 sagt nicht definiert. Um dies zu beheben, müssen Sie sie als p1 = (charP1, numP1) und p2 = (charP2, numP2) setzen. Um dies mit Ihrer Syntax zu lösen Sie folgendes tun:

def sortAndAggregateList(chars: List[(Char, Int)]) : List[(Char, Int)] = { 
    chars match { 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 > charP2) => 
     sortList((charP1, numP1) :: (charP2, numP2) :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 < charP2) => 
     sortList((charP2, numP2) :: (charP1, numP1) :: x) 
    case (charP1, numP1) :: (charP2, numP2) :: x if (charP1 == charP2) => 
     val p3: (Char, Int) = (charP1, numP1 + numP2) 
     sortList(p3 :: x) 
    case x => 
     x 
    case Nil => 
     Nil 
    } 
} 

Nun ist die einzige fehlende Glied der sortList Funktion, die Sie haben nicht hinzugefügt. Ich bin mir nicht sicher, ob dies funktionieren wird, weil ich den Fall denken:

case x => x 

sein sollte:

case x :: Nil => x :: Nil 

Sonst würde x nichts gefunden.Welche lässt Sie auch die Möglichkeit, den Fall entfernen:

case Nil => Nil 

wenn Sie wollen Fall nicht entfernen x => x

+0

dieser 'Fall x => x' wird funktionieren – pamu

+0

ja du hast Recht Deshalb habe ich hinzugefügt, dass es zu allem passt, sogar zu Nil. – biro

+0

Fall Nil => Nil ist überflüssig – pamu

0

Extra Typ Annotation nach x ist nicht notwendig und falsch.

entfernen diese

(x : List[(String, Int)]) 

stattdessen verwenden (nicht zwingend. Sie können die Typanmerkung weglassen)

(x : List[(Char, Int)]) 

komplette Funktion

def sortAndAggregateList(chars: List[(Char, Int)]): List[(Char, Int)] = chars match { 
    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 > charP2 => 

     sortAndAggregateList((charP2, numP2) :: (charP1, numP1) :: x) 

    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 < charP2 => 

     sortAndAggregateList((charP1, numP1) :: (charP2, numP2) :: x) 

    case (charP1, numP1) :: (charP2, numP2) :: x if charP1 == charP2 => 

     sortAndAggregateList((charP1, numP1 + numP2) :: x) 

    case x => x 
    } 

Der Code wird viel sauberer sein, wenn Sie betrachten das Zusammenfallen der Tupel

def sortAndAggregateList(chars: List[(Char, Int)]): List[(Char, Int)] = chars match { 
    case a :: b :: x if a._1 > b._2 => 

     sortAndAggregateList(b :: a :: x) 

    case a :: b :: x if a._1 < b._1 => 

     sortAndAggregateList(a :: b :: x) 

    case a :: b :: x if a._1 == b._1 => 

     sortAndAggregateList((a._1, (a._2 + b._2)) :: x) 

    case x => x 

    } 

Fall case x => x wird sowohl Liste Nil Fall und Liste mit einem Element Fall übereinstimmen.

+0

Diese Funktion hat eine Schwäche. Es funktioniert nicht mit einer Liste mit nur einem Eintrag wie: Liste (("t", 1)) – biro

+0

@biro danke für den Vorschlag behoben – pamu