2016-04-20 14 views
1

Ich möchte eine Funktion, die eine Zeichenfolge aus mehreren "Noten" unterschiedlicher Länge nimmt und es in eine Liste von Noten konvertieren.Konvertieren Sie eine Zeichenfolge in eine Liste von "Noten"

Grade sind nur eine Datenstruktur, die (nur ein willkürliches Notensystem) wie folgt aussieht:

data Grade = A+ | A | A- | B+ | B | B- | P | F 
    deriving (Show, Eq) 

Wie Sie sehen können, die Noten haben unterschiedliche Länge. Wenn sie Länge 1 oder konsistente Länge hätten, wäre das viel einfacher gewesen. Hier

ist die Funktion, die ich machen möchte:

Dies ist, was die String-Eingang sieht aus wie "PA+FABA+B-A"

stringToGrade :: String -> Grade 
stringToGrade stringGrade 
    | stringGrade == "A+" = A+ 
    | stringGrade == "A" = A 
    -- and so on 

extractGrades :: String -> [Grade] 
extractGrades stringGrades = case stringGrades of 
    [] -> [] 
    x:y:ys 
    | x == "A" && y == "+" -> [stringToGrade (x : y)] : extractGrades ys 
    | x == "A" -> [stringToGrade x] : extractGrades y:ys 
    -- and so on 

Wie Sie sehen können, ist dies nicht überall geht.

Gibt es einen eleganten und einfachen Weg, den ich cam mache anstatt alles zu programmieren?

+0

Wird es irgendwelche Trennzeichen zwischen Noten in der Zeichenfolge? (Es ist ein gut gestelltes Problem auch ohne das, aber es ist einfacher so ...) –

+0

Oh, ich werde die Frage bearbeiten. Es sieht so aus "A + FABA + B-A" ' – user6005857

+0

Ich möchte nicht, dass es durch alphabetische Zeichen geteilt wird, weil ich möchte, dass dies für Datenstrukturen funktioniert, die denselben Typ haben. – user6005857

Antwort

4

Wir können die Mustererkennung so anpassen, dass sie einem String-Präfix entspricht. Hier ein Beispiel:

foo :: String -> [Int] 
foo [] = [] 
foo ('h':'e':'l':'l':'o':rest) = 1 : foo rest 
foo ('b':'o':'b':rest) = 2 : foo rest 
foo ('b':rest) = 3 : foo rest 
foo _ = error "foo: invalid input syntax" 

Verwendungsbeispiel:

foo "hellobbobbobhello" ==> [1,3,2,2,1] 
0

Sie können die Zeichenfolge in Token aufgeteilt Kombination von Split-Funktionen.

split (keepDelimsR $ oneOf "+-") "PA+FABA+B-A" 

wird dieses Formular erstellen, wo die Suffixe angehängt sind.

["PA+","FABA+","B-","A"] 

Jetzt können Sie diese geteilt weiter mit einem benutzerdefinierten Teiler

splitInit [] = [] 
splitInit [x] = [[x]] 
splitInit [x,y] = [[x,y]] 
splitInit (x:xs) = [x] : splitInit xs 

eine Kombination geben Ihnen

concatMap splitInit $ split (keepDelimsR $ oneOf "+-") "PA+FABA+B-A" 
["P","A+","F","A","B","A+","B-","A"] 

, wo Sie durch Ihre Konstrukteure abbilden

Verwandte Themen