Dans Haskell, comment découpez-vous les espaces depuis le début et la fin d’une chaîne?

Comment découpez-vous les espaces à partir du début et de la fin d’une chaîne?

sortingm " abc " => "abc" 

Modifier:

Ok, laissez-moi être un peu plus clair. Je n’ai pas compris que les littéraux de chaîne étaient traités différemment des chaînes de caractères.

Je voudrais faire ceci:

 import qualified Data.Text as T let s :: Ssortingng = " abc " in T.ssortingp s 

Est-ce possible à Haskell? J’utilise -XOverloadedSsortingngs mais cela ne semble fonctionner que pour les littéraux.

Si vous avez des besoins sérieux en traitement de texte, utilisez alors le package de text de hackage:

 > :set -XOverloadedSsortingngs > import Data.Text > ssortingp " abc " "abc" 

Si vous êtes trop têtu pour utiliser du text et que vous n’aimez pas l’inefficacité de la méthode inverse, alors peut-être (et je veux dire, peut-être) que quelque chose comme ci-dessous sera plus efficace:

 import Data.Char sortingm xs = dropSpaceTail "" $ dropWhile isSpace xs dropSpaceTail maybeStuff "" = "" dropSpaceTail maybeStuff (x:xs) | isSpace x = dropSpaceTail (x:maybeStuff) xs | null maybeStuff = x : dropSpaceTail "" xs | otherwise = reverse maybeStuff ++ x : dropSpaceTail "" xs > sortingm " hello this \t should sortingm ok.. .I think .. \t " "hello this \t should sortingm ok.. .I think .." 

J’ai écrit ceci en supposant que la longueur des espaces serait minime, de sorte que votre O (n) de ++ et reverse est peu préoccupant. Mais encore une fois, je ressens le besoin de dire que si vous êtes réellement préoccupé par la performance, vous ne devriez pas utiliser Ssortingng du tout – passez à Text .

EDIT en faisant mon point, un rapide test de critère me dit que (pour une chaîne de mots particulièrement longue avec des espaces et environ 200 espaces pré et post), mon sortingm prend 1,6 ms, le sortingm en reverse prend 3,5 ms et Data.Text.ssortingp prend 0.0016 ms …

De: http://en.wikipedia.org/wiki/Trim_(programming)#Haskell

 import Data.Char (isSpace) sortingm :: Ssortingng -> Ssortingng sortingm = f . f where f = reverse . dropWhile isSpace 

Après que cette question a été posée (circa 2012)

 sortingm = dropWhileEnd isSpace . dropWhile isSpace 

Inefficace mais facile à comprendre et à coller là où cela est nécessaire:

 ssortingp = lssortingp . rssortingp lssortingp = dropWhile (`elem` " \t") rssortingp = reverse . lssortingp . reverse 

Pour sûr, Data.Text est meilleur pour la performance. Mais, comme cela a été mentionné, il est amusant de le faire avec des listes. Voici une version qui reprend la chaîne en un seul passage (sans reverse et ++) et supporte des listes infinies:

 rssortingp :: Ssortingng -> Ssortingng rssortingp str = let (zs, f) = go str in if f then [] else zs where go [] = ([], True) go (y:ys) = if isSpace y then let (zs, f) = go ys in (y:zs, f) else (y:(rssortingp ys), False) 

ps comme pour les listes infinies, cela fonctionnera:

 List.length $ List.take n $ rssortingp $ cycle "abc " 

et, pour des raisons évidentes, cela ne fonctionnera pas (sera éternel):

 List.length $ List.take n $ rssortingp $ 'a':(cycle " ") 

Vous pouvez combiner la ssortingp Data.Text avec ses fonctions un / packing pour éviter de surcharger les chaînes:

 import qualified Data.Text as T ssortingp = T.unpack . T.ssortingp . T.pack lssortingp = T.unpack . T.ssortingpStart . T.pack rssortingp = T.unpack . T.ssortingpEnd . T.pack 

Le tester:

 > let s = " hello " > ssortingp s "hello" > lssortingp s "hello " > rssortingp s " hello" 

Aujourd’hui, le paquet MissingH livré avec une fonction ssortingp :

 import Data.Ssortingng.Utils mySsortingng = " foo bar " -- ssortingp :: Ssortingng -> Ssortingng myTrimmedSsortingng = ssortingp mySsortingng -- myTrimmedSsortingng == "foo bar" 

Donc, si la conversion de Ssortingng en Text et back n’a pas de sens dans votre situation, vous pouvez utiliser la fonction ci-dessus.

Je sais que c’est un ancien message, mais je n’ai vu aucune solution qui implémente le bon vieux temps.

dropWhile abord l’espace blanc principal en utilisant dropWhile . Ensuite, en utilisant foldl' et une simple fermeture, vous pouvez parsingr le rest de la chaîne en une seule fois et, en fonction de cette parsing, passer ce paramètre informatif sans avoir à reverse :

 import Data.Char (isSpace) import Data.List (foldl') sortingm :: Ssortingng -> Ssortingng sortingm s = let s' = dropWhile isSpace s sortingm' = foldl' (\(c,w) x -> if isSpace x then (c,w+1) else (c+w+1,0)) (0,0) s' in take (fst sortingm') s' 

La variable c garde la trace des espaces blancs et non blancs combinés qui doivent être absorbés, et la variable w garde la trace des espaces blancs du côté droit à supprimer.

Essais:

 print $ sortingm " abc " print $ sortingm " ab c " print $ sortingm " abc " print $ sortingm "abc" print $ sortingm "a bc " 

Sortie:

 "abc" "ab c" "abc" "abc" "a bc" 

Je ne sais rien à propos de l’exécution ou de l’efficacité, mais qu’en est-il de cela:

 -- entirely input is to be sortingmmed sortingm :: Ssortingng -> Ssortingng sortingm = Prelude.filter (not . isSpace') -- just the left and the right side of the input is to be sortingmmed lrsortingm :: Ssortingng -> Ssortingng lrsortingm = \xs -> rsortingm $ lsortingm xs where lsortingm = dropWhile (isSpace') rsortingm xs | Prelude.null xs = [] | otherwise = if isSpace' $ last xs then rsortingm $ init xs else xs -- returns True if input equals ' ' isSpace' :: Char -> Bool isSpace' = \c -> (c == ' ') 

Une solution sans utiliser aucun autre module ou bibliothèque que le Prélude.

Quelques tests:

 >lrsortingm "" >"" >lrsortingm " " >"" >lrsortingm "haskell " >"haskell" >lrsortingm " haskell " >"haskell" >lrsortingm " haske ll " >"haske ll" 

Cela pourrait être le runtime O (n).

Mais je ne le sais pas parce que je ne connais pas le temps d’exécution des fonctions en dernier et init. 😉

À l’instar de ce que d’autres personnes ont suggéré, vous pouvez éviter d’avoir à inverser votre chaîne en utilisant:

 import Data.Char (isSpace) dropFromTailWhile _ [] = [] dropFromTailWhile p item | p (last items) = dropFromTailWhile p $ init items | otherwise = items sortingm :: Ssortingng -> Ssortingng sortingm = dropFromTailWhile isSpace . dropWhile isSpace 

Cela devrait être juste à propos de O (n), je crois:

 import Data.Char (isSpace) sortingm :: Ssortingng -> Ssortingng -- Trimming the front is easy. Use a helper for the end. sortingm = dropWhile isSpace . sortingm' [] where sortingm' :: Ssortingng -> Ssortingng -> Ssortingng -- When finding whitespace, put it in the space bin. When finding -- non-whitespace, include the binned whitespace and continue with an -- empty bin. When at the end, just throw away the bin. sortingm' _ [] = [] sortingm' bin (a:as) | isSpace a = sortingm' (bin ++ [a]) as | otherwise = bin ++ a : sortingm' [] as 

Une autre solution (std)

 import System.Environment import Data.Text ssortingp :: Ssortingng -> IO Ssortingng ssortingp = return . unpack . Data.Text.ssortingp . pack main = getLine >>= Main.ssortingp >>= putStrLn