2017-09-20 4 views
2

Ich muß überprüfen, ob letztes Element der Liste Zum Beispiel "abc" groß geschrieben wird - False, "abC"-TrueHaskell - überprüfen letztes Element der Liste

Das ist, was ich versuchte

checkLast :: [a] -> Bool 
checkLast [] = False 
checkLast [x] = if isUpper x then True else False 
checkLast (x:xs) = if isUpper last then True else False 
+4

Ein paar Dinge.** 1 ** 'wenn isUpper x dann True else False ist das gleiche wie' isUpper x'. ** 2 ** Werfen Sie einen zweiten Blick auf den letzten Fall. Woher bekommst du 'last'? Warum ist 'x: xs' unbenutzt? – SwiftsNamesake

Antwort

3

Denken rekursiv. checkLast (x:xs) prüft gerade checkLast xs:

checkLast :: [Char] -> Bool 
checkLast [] = False 
checkLast [x] = isUpper x 
checkLast (x:xs) = checkLast xs 

Beachten Sie, dass da Sie isUpper verwenden Strings zu überprüfen, macht es mehr Sinn, dass der Typ [Char] sein sollte, nicht [a].

1

Eine feste Version mit Kommentaren:

import Data.Char (isUpper) 

checkLast :: [Char] -> Bool  -- it cannot be [a]: use of isUpper already limits possible type to [Char] 
checkLast [] = False 
checkLast [x] = isUpper x  -- the if .. can be shorter 
checkLast (x:xs) = checkLast xs -- drop first char and look at rest of string 
2

Sie können von Rekursion machen wie die anderen Antworten zeigen. Sie können jedoch auch Butintins verwenden, um eine solche Funktion zu erstellen.

Zwei relevante Funktionen sind hier null :: [a] -> Bool, die prüft, ob eine Liste leer ist, und last :: [a] -> a, die das letzte Element erhält.

So, jetzt können wir eine Funktion konstruieren:

import Data.Char(isUpper) 

checkLast :: [Char] -> Bool 
checkLast l = not (null l) && isUpper (last l) 

So, hier wir feststellen, dass checkLast ist True, wenn die Liste l nicht leer ist (not (null l)); und das letzte Element ist ein Großbuchstabe isUpper (last l).

Dies wird wahrscheinlich ein bisschen schneller sein als die rekursiven Funktionen, da wir den [] Fall nur einmal testen (in null). last prüft nur zwei Fälle: [x] und (x:xs) so sparen wir [] prüft.

Natürlich ist diese Funktionen mit Rekursion arbeiten, aber es ist manchmal nützlich für Hilfsfunktionen zu suchen, so dass eine Funktion fast selbsterklärend: hier die Funktionen sagen: "Eine Liste l ist checkLast wenn es nicht leer ist, und das letzte Element ist ein Großbuchstabe ".

+0

Ich hatte den Eindruck, dass es eine Aufgabe ist, angesichts der leicht konstruierten Frage und der Art und Weise, wie das OP sich ihm näherte. – SwiftsNamesake

+0

Ich denke, es ist besser, die Gesamtfunktionen als Teilfunktionen zu schützen. – dfeuer

-2

Sie können auch ohne Rekursion wie folgt tun

import Data.Char 

checkLast :: String -> Bool 
checkLast = (&&) <$> not . null <*> isUpper . head . reverse 

Der applicative Operator ist <*> ein ideales Werkzeug einen gemeinsamen Parameter (der Eingabestring hier) zwei verschiedene Funktionen wie not . null und isUpper . head . reverse und dann zu füttern um eine Operation (&&) auf ihr Ergebnis zu machen.

Laut @ dfeuer Kommentar Ich möchte nur die folgende Lösung für eine bessere Leistung anfügen. Sie brauchen kein anderes Paket zu importieren, als Data.Char

import Data.Char 

checkLast :: String -> Bool 
checkLast [] = False 
checkLast cs = isUpper $ foldr1 seq cs 
+1

Dies ist jedoch eine schreckliche Lösung. Abgesehen davon, dass es kompliziert ist, baut es auch eine umgekehrte Zeichenfolge auf, um nur ein Element zu betrachten und den Rest wegzuwerfen. Es ist furchtbar ineffizient. – dfeuer

+0

@dfeuer Wie ist dieses Code-Snippet wirklich kompliziert? Dies ist ein sehr einfaches Muster in Haskell. Nach Ineffizienz glaube ich, dass es nicht zeitaufwändig ist, aber ja ... Raumweise könnte man 'last' anstelle von' head' verwenden. umgekehrt. – Redu

+1

Die Verwendung der "Applicative" -Instanz für Funktionen erscheint mir in diesem Fall eher als Verschleiern als Erklären. – dfeuer

1

Der einfachste Weg, explizite Rekursion zu vermeiden, wenn Sie dies tun wollen, ist wahrscheinlich eine Falte zu verwenden:

lastMay :: [a] -> Maybe a 
lastMay = foldl' (\_ x -> Just x) Nothing 

checkLast = maybe True isUpper . lastMay 
+0

Dies ist auch eine schreckliche Lösung, da Sie das Paket "Data.Maybe" einfach importieren müssen, um diese einfache Aufgabe zu implementieren. Es ist total nicht nötig. Siehe meine Antwort im Anhang. – Redu

+0

@Redu, die einzige Nicht-Vorspiel-Funktion, die ich benutzt habe, ist 'foldl'. Aber Basisimporte sind ohnehin gutartig. – dfeuer