66 votes

En Haskell, comment couper les espaces blancs du début et de la fin d'une chaîne de caractères ?

Comment couper les espaces blancs au début et à la fin d'une chaîne de caractères ?

trim "  abc " 

=>

"abc"

Edit :

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

J'aimerais le faire :

import qualified Data.Text as T
let s :: String = "  abc  "
in T.strip s

Est-ce possible en Haskell ? J'utilise -XOverloadedStrings mais cela ne semble fonctionner que pour les littéraux.

66voto

Thomas M. DuBuisson Points 31851

Si vous avez des besoins sérieux en matière de traitement de texte, utilisez la fonction text paquet de hackage :

> :set -XOverloadedStrings
> import Data.Text
> strip "  abc   "
"abc"

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

import Data.Char

trim 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

> trim "  hello this \t should trim ok.. .I  think  ..  \t "
"hello this \t should trim ok.. .I  think  .."

J'ai écrit ceci en supposant que la longueur des espaces serait minimale, donc votre O(n) de ++ y reverse est peu préoccupant. Mais une fois de plus, je ressens le besoin de dire que si vous êtes réellement préoccupé par les performances, alors vous ne devriez pas utiliser le système de gestion de l'information. String du tout - passer à Text .

EDIT pour illustrer mon propos, un rapide benchmark Criterion m'indique que (pour une chaîne de mots particulièrement longue avec des espaces et ~200 espaces avant et après) mon découpage prend 1,6 ms, le découpage utilisant la marche arrière prend 3,5 ms, et Data.Text.strip prend 0.0016 ms...

4 votes

Merci pour la recommandation. J'ai convaincu mon équipe d'ajouter du texte au projet et cela m'évite bien des maux de tête.

5 votes

+1 pour le benchmark, c'est génial quand les gens prouvent vraiment leurs affirmations.

53voto

Eric Normand Points 2030

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

import Data.Char (isSpace)

trim :: String -> String
trim = f . f
   where f = reverse . dropWhile isSpace

18 votes

Et c'est le plus simple. Pour un cas d'utilisation rapide et simple, c'est bien.

6 votes

C'est magnifique, bien que j'aurais utilisé un let la reliure.

48voto

spopejoy Points 21

Après que cette question ait été posée (circa 2012) Data.List obtenu dropWhileEnd ce qui rend les choses beaucoup plus faciles :

trim = dropWhileEnd isSpace . dropWhile isSpace

3 votes

Pour ceux qui s'embrouillent avec l'opérateur point (utilisé pour la composition de fonctions), ceci est équivalent à trim :: String -> String trim xs = dropWhile isSpace (dropWhileEnd isSpace xs) . stackoverflow.com/questions/631284/ hackage.haskell.org/package/base-4.12.0.0/docs/

2 votes

Pour les débutants (comme moi) : Cette solution nécessite d'abord que vous import Data.List y import Data.Char .

16voto

Simon Michael Points 1577

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

strip = lstrip . rstrip
lstrip = dropWhile (`elem` " \t")
rstrip = reverse . lstrip . reverse

4voto

John J. Camilleri Points 589

Vous pouvez combiner Data.Text 's strip avec ses fonctions de dépaquetage et d'empaquetage pour éviter d'avoir des chaînes surchargées :

import qualified Data.Text as T

strip  = T.unpack . T.strip . T.pack
lstrip = T.unpack . T.stripStart . T.pack
rstrip = T.unpack . T.stripEnd . T.pack

Je le teste :

> let s = "  hello  "
> strip s
"hello"
> lstrip s
"hello  "
> rstrip s
"  hello"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X