2016-03-20 2 views
0

Wie ersetze ich ein Zeichen durch mehrere Zeichen in einer Zeichenfolge. Ich kann mit unten, um ein Zeichen durch ein anderes Zeichen ersetzt werden:Haskell String ersetzen

replaceO [] = [] 
    replaceO (x:xs) = 
    if x == '(' 
    then '\n' : replaceO xs 
    else x : replaceO xs 

Aber ich mag ersetzen '(' mit "\ n \ t \ t", nicht nur '\ n'

-. -------- UPDATE -------------- Basierend auf der Antwort unten, kann ich machen, dass eine Funktion, die einen String und gibt eine Zeichenfolge wie folgt akzeptiert:

ReplaceFun str :: String -> String 
ReplaceFun str = do 
    concatMap (\str -> if str == '.' then "foo" else [str]) 

Das funktioniert nicht, kann jemand auf meinen Fehler hinweisen? Ich bin sehr neu in Haskell.

Hier

ist, was ich für verschachtelte Einbuchtung haben:

replaceO (x:xs) n l = 
    if x == '(' 
    then "\n" ++ (showTabs n "-") ++ replaceO xs (n + 1) 'l' 
    else 
     if x == ')' 
     then "\n" ++ (showTabs n "-") ++ replaceO xs (n - 1) 'l' 
     else x : replaceO xs n 'l' 
+1

Sie haben 'concatMap' nicht genügend Argumente gegeben - die rhs von' replaceFun' (beachten Sie auch den Kleinbuchstaben) sollte den Typ 'String' haben, aber' concatMap (\ str -> if str == ').'then' foo 'else [str]) 'hat den Typ' String -> String'. Du willst wahrscheinlich 'replaceFun = concatMap (\ str -> wenn str == '.' Dann 'foo' else [str])' – user2407038

Antwort

5

Gerade concatMap

Prelude> concatMap (\x -> if x == '.' then "foo" else [x]) "example..." 
"examplefoofoofoo" 
+0

Kannst du das bitte als Funktion definieren? Ich kann es nicht funktionieren. – 2D3D4D

+0

Ich habe es so gemacht, funktioniert aber nicht: replaceFun w :: String -> String ersetzenFun w = tun concatMap (\ x -> wenn x == '.' Dann "foo" else [x]) – 2D3D4D

+0

können Sie Werfen Sie einen Blick auf den aktualisierten Teil der Frage? – 2D3D4D

2

Erweiterung Ihres Beispiel verwenden, können Sie ersetzen "\ n \ t \ t" für "(" von nur mehrere Dinge auf das Ergebnis des rekursiven Aufruf voranstellen

replace1 [] = [] 
replace1 (x:xs) = 
    if x == '(' 
    then '\n' : '\t' : '\t' : replace1 xs 
    else x : replace1 xs 

natürlich ist dies äquivalent zur Verwendung von "\n\t\t" ++

replace2 [] = [] 
replace2 (x:xs) = 
    if x == '(' 
    then "\n\t\t" ++ replace2 xs 
    else x : replace2 xs 

wenn wir feststellen, dass x : äquivalent zu [x] ++

replace3 [] = [] 
replace3 (x:xs) = 
    if x == '(' 
    then "\n\t\t" ++ replace3 xs 
    else [x] ++ replace3 xs 

dann können wir

replace4 [] = [] 
replace4 (x:xs) = (if x == '(' then "\n\t\t" else [x]) ++ replace4 xs 

dann die wiederholte rekursiven Aufruf ausklammern für Klarheit, könnten wir die if Aussage herauszufiltern in eine Funktion:

replace5 [] = [] 
replace5 (x:xs) = f x ++ replace5 xs 
    where f x = if x == '(' 
       then "\n\t\t" 
       else [x] 

dann könnten wir unseren Code reorganisieren - anstatt abwechselnd f zu jedem x und es um unsere Ergebnisse der Anwendung anhängt, könnten wir f auf alle xs anwenden und dann alle Ergebnisse verketten:

replace6 xs = concat $ map f xs 
    where f x = if x == '(' 
       then "\n\t\t" 
       else [x] 

Aber concat $ map f xs so oft verwendet wird, dass es einen anderen Namen hat:

replace7 xs = concatMap f xs 
    where f x = if x == '(' 
       then "\n\t\t" 
       else [x] 

Eigentlich hat es ein anderes auch, weil [] eine Monade ist:

replace8 xs = xs >>= f 
    where f x = if x == '(' 
       then "\n\t\t" 
       else [x] 

Aber wenn wir das tun, können wir auch voll Monade gehen:

replace9 xs = do 
    x <- xs 
    if x == '(' 
    then "\n\t\t" 
    else [x] 

Aber ich würde wahrscheinlich nur bei replace7 stoppen, persönlich.

+0

Danke @rampion, gerade etwas realisiert, ich wollte das verwenden, um einen Baum hübsch zu drucken. Aber alle Knoten enden in der gleichen Einrückung. Ich wollte die Einrückung für jeden verschachtelten Knoten erhöhen. Ist das leicht möglich? – 2D3D4D

+1

Sicher! schau dir eine der frühen Versionen an. Was ist, wenn 'replace2' ein anderes Argument,' n', für die Anzahl der zu einzufügenden Registerkarten nach dem Ersetzen eines '(' mit einem Zeilenumbruchzeichen) verwendet? Nun benötigt der rekursive Aufruf zwei Argumente - den Rest der Zeichenfolge und die Anzahl der Registerkarten würden Sie den rekursiven Aufruf geben, wenn (a) 'x' keine Klammer wäre, (b) es ein offener Paren oder (c) ein enger Paren wäre? – rampion

+0

Wenn es keine Klammer wäre, dann ist kein Ersatz erforderlich Wenn eine öffnende Klammer, dann ersetzen wir \ n und \ t (für jede verschachtelte Ebene). Klammer kann durch leere Zeichenfolge ersetzt werden, denke ich. – 2D3D4D