web-dev-qa-db-fra.com

Supprimer des caractères spécifiques d'une chaîne en Python

J'essaie de supprimer des caractères spécifiques d'une chaîne en utilisant Python. C'est le code que j'utilise en ce moment. Malheureusement, il semble ne rien faire pour la chaîne.

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

Comment puis-je le faire correctement?

415
Matt Phillips

Les chaînes en Python sont immuable (ne peuvent pas être changées). De ce fait, l’effet de line.replace(...) est simplement de créer une nouvelle chaîne, plutôt que de changer l’ancienne. Vous devez rebind (l'attribuer) à line pour que cette variable prenne la nouvelle valeur, ces caractères étant supprimés.

En outre, votre façon de faire va être un peu lente, relativement. Cela risque également d'être un peu déroutant pour les pythonateurs expérimentés, qui verront une structure imbriquée deux fois et penseront un instant que quelque chose de plus compliqué se passe.

À partir de Python 2.6 et des versions plus récentes de Python 2.x *, vous pouvez utiliser à la place str.translate , (mais lisez la suite pour connaître les différences entre Python 3):

line = line.translate(None, '!@#$')

ou remplacement d'une expression régulière avec re.sub

import re
line = re.sub('[!@#$]', '', line)

Les caractères entre crochets constituent une classe de caractères . Tous les caractères de line qui sont dans cette classe sont remplacés par le deuxième paramètre de sub: une chaîne vide.

En Python 3, les chaînes sont au format Unicode. Vous devrez traduire un peu différemment. kevpie mentionne cela dans un commentaire sur l'une des réponses, et cela est noté dans la documentation pour str.translate .

Lorsque vous appelez la méthode translate d'une chaîne Unicode, vous ne pouvez pas transmettre le deuxième paramètre que nous avons utilisé ci-dessus. Vous ne pouvez pas non plus passer None comme premier paramètre, ni même une table de traduction de string.maketrans. Au lieu de cela, vous transmettez un dictionnaire comme seul paramètre. Ce dictionnaire mappe les valeurs ordinales de caractères (c'est-à-dire le résultat de l'appel de ord ) avec les valeurs ordinales des caractères qui doivent les remplacer, ou - utilement pour nous --None pour indiquer que ils devraient être supprimés.

Donc, pour faire la danse ci-dessus avec une chaîne Unicode, vous appelez quelque chose comme

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

Ici, dict.fromkeys et map sont utilisés pour générer de manière succincte un dictionnaire contenant

{ord('!'): None, ord('@'): None, ...}

Encore plus simple, comme une autre réponse le dit , créez le dictionnaire en place:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

* pour assurer la compatibilité avec les Pythons antérieurs, vous pouvez créer une table de traduction "null" à transmettre à la place de None:

import string
line = line.translate(string.maketrans('', ''), '!@#$')

Ici, string.maketrans est utilisé pour créer une table translation, qui est simplement une chaîne contenant les caractères dont les valeurs ordinales sont comprises entre 0 et 255.

528
intuited

Est-ce que je manque le point ici, ou est-ce juste ce qui suit:

>>> string = "ab1cd1ef"
>>> string.replace("1","")
'abcdef'
>>>

Mettez-le en boucle:

>>>
>>> a = "a!b@c#d$"
>>> b = "!@#$"
>>> for char in b:
...     a = a.replace(char,"")
...
>>> print a
abcd
>>>
180
gsbabil
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'
37
ghostdog74

Peasy facile avec re.sub en Python 3.5

re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

Exemple

>>> import re

>>> line = 'Q: Do I write ;/.??? No!!!'

>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'

Explication

Dans expressions régulières (regex), | est un OR logique et \ échappe aux espaces et aux caractères spéciaux pouvant être de véritables commandes de regex. sub signifie substitution.

20
Serge Stroobandt

Pour l'exigence inverse de seulement autorisant certains caractères dans une chaîne, vous pouvez utiliser des expressions régulières avec un opérateur de jeu complémentaire, [^ABCabc]. Par exemple, pour tout supprimer à l'exception des lettres ascii, des chiffres et du trait d'union:

>>> import string
>>> import re
>>>
>>> phrase = '  There were "nine" (9) chick-peas in my pocket!!!      '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)

'Therewerenine9chick-peasinmypocket'

De la documentation sur les expressions rationnelles python :

Les caractères qui ne sont pas dans une plage peuvent être appariés en complétant l'ensemble. Si le premier caractère du jeu est '^', tous les caractères qui ne sont pas dans l'ensemble seront appariés. Par exemple, [^5] correspondra à n'importe quel caractère sauf '5', et [^^] correspond à n'importe quel caractère sauf '^'. ^ n'a pas de signification particulière s'il ne s'agit pas du premier caractère du caractère ensemble.

18
cod3monk3y

Le demandeur l'a presque eu. Comme la plupart des choses en Python, la réponse est plus simple que vous ne le pensez.

>>> line = "H E?.LL!/;O:: "  
>>> for char in ' ?.!/;:':  
...  line = line.replace(char,'')  
...
>>> print line
HELLO

Vous n'avez pas à faire la boucle imbriquée if/for, mais vous devez vérifier chaque caractère individuellement.

18
mgold
line = line.translate(None, " ?.!/;:")
14
Muhammad Alkarouri
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
10
eatkin

Les chaînes sont immuables en Python. La méthode replace renvoie une nouvelle chaîne après le remplacement. Essayer:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
7
Greg Hewgill

Avec filter , vous n’auriez besoin que d’une seule ligne

line = filter(lambda char: char not in " ?.!/;:", line)

Ceci traite la chaîne comme une variable itérable et vérifie chaque caractère si la variable lambda renvoie True:

>>> help(filter)
Help on built-in function filter in module __builtin__:

filter(...)
    filter(function or None, sequence) -> list, Tuple, or string

    Return those items of sequence for which function(item) is true.  If
    function is None, return the items that are true.  If sequence is a Tuple
    or string, return the same type, else return a list.
5
serv-inc

J'ai été surpris que personne n'ait encore recommandé l'utilisation de la fonction intégrée filtre une fonction.

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

Disons que nous voulons filtrer tout ce qui n'est pas un nombre. L'utilisation de la méthode intégrée du filtre "... est équivalente à l'expression du générateur (élément pour élément dans iterable if function (élément))" "[ Python 3 Filtre ]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

En Python 3, cela retourne 

    >>  <filter object @ hex>

Pour obtenir une chaîne imprimée,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

Je ne sais pas comment filtre se classe en termes d’efficacité, mais c’est une bonne chose de savoir comment l’utiliser lors de la compréhension de listes et autres.

METTRE À JOUR

Logiquement, puisque les filtres fonctionnent, vous pouvez également utiliser la compréhension de liste. D'après ce que j'ai lu, il est censé être plus efficace, car les lambdas sont les gestionnaires de hedge funds de Wall Street du monde de la fonction de programmation. Un autre avantage est que c'est un one-line qui ne nécessite aucune importation. Par exemple, en utilisant la même chaîne 's' définie ci-dessus,

      num = "".join([i for i in s if i.isdigit()])

C'est tout. Le retour sera une chaîne de tous les caractères qui sont des chiffres dans la chaîne d'origine.

Si vous avez une liste spécifique de caractères acceptables/inacceptables, il vous suffit d'ajuster la partie "Si" de la compréhension de la liste.

      target_chars = "".join([i for i in s if i in some_list]) 

ou bien,

      target_chars = "".join([i for i in s if i not in some_list])
5
Dan Temkin
>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
4
Arihant Bansal

Voici quelques moyens possibles pour réaliser cette tâche:

def attempt1(string):
    return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])


def attempt2(string):
    for v in ("a", "e", "i", "o", "u"):
        string = string.replace(v, "")
    return string


def attempt3(string):
    import re
    for v in ("a", "e", "i", "o", "u"):
        string = re.sub(v, "", string)
    return string


def attempt4(string):
    return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")


for attempt in [attempt1, attempt2, attempt3, attempt4]:
    print(attempt("murcielago"))

PS: Au lieu d’utiliser "?.!/;:", les exemples utilisent les voyelles ... et oui, "murcielago" est le mot espagnol qui veut dire bat ... un mot drôle car il contient toutes les voyelles :)

PS2: Si les performances vous intéressent, vous pouvez mesurer ces tentatives avec un code simple comme:

import timeit


K = 1000000
for i in range(1,5):
    t = timeit.Timer(
        f"attempt{i}('murcielago')",
        setup=f"from __main__ import attempt{i}"
    ).repeat(1, K)
    print(f"attempt{i}",min(t))

Dans ma boîte, vous auriez:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

Il semble donc que tentative4 soit la plus rapide pour cette entrée particulière.

3
BPL

Voici ma version compatible Python 2/3. Depuis que l'API de traduction a changé. 

def remove(str_, chars):
    """Removes each char in `chars` from `str_`.

    Args:
        str_: String to remove characters from
        chars: String of to-be removed characters

    Returns:
        A copy of str_ with `chars` removed

    Example:
            remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
    """
    try:
        # Python2.x
        return str_.translate(None, chars)
    except TypeError:
        # Python 3.x
        table = {ord(char): None for char in chars}
        return str_.translate(table)
3
Bryce Guinta

Vous pouvez également utiliser une fonction afin de substituer un type différent d’expression régulière ou un autre motif à l’utilisation d’une liste. Avec cela, vous pouvez mélanger une expression régulière, une classe de caractères et un motif de texte très basique. C'est vraiment utile lorsque vous devez substituer beaucoup d'éléments comme ceux en HTML.

* NB: fonctionne avec Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

Dans la fonction string_cleanup, il utilise votre chaîne x et votre liste comme arguments. Pour chaque élément de cette liste d'éléments ou de motifs, un remplacement est nécessaire.

Le résultat:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean
1
Djidiouf
#!/usr/bin/python
import re

strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr
1
pkm

Que dis-tu de ça:

def text_cleanup(text):
    new = ""
    for i in text:
        if i not in " ?.!/;:":
            new += i
    return new
1
Wariat

Vous devez réaffecter votre variable str:

for char in line:
if char in " ?.!/;:":
    line = line.replace(char,'')
1
Anastasia Churyk

Ma méthode que j'utiliserais ne fonctionnerait probablement pas aussi efficacement, mais elle est extrêmement simple. Je peux supprimer plusieurs caractères à différentes positions en même temps, en utilisant le découpage en tranches et le formatage ..__ Voici un exemple:

words = "things"
removed = "%s%s" % (words[:3], words[-1:])

Cela se traduira par «enlevé» en tenant le mot «ceci».

Le formatage peut être très utile pour imprimer des variables au milieu d’une chaîne d’impression. Il peut insérer n'importe quel type de données en utilisant un% suivi du type de données de la variable; tous les types de données peuvent utiliser% s , et les éléments flottants (ou décimales) et les entiers peuvent utiliser% d

Slicing peut être utilisé pour un contrôle complexe des chaînes. Quand je mets words [: 3] , cela me permet de sélectionner tous les caractères de la chaîne depuis le début (les deux points sont avant le nombre, cela signifiera du début à la fin) jusqu'au 4ème caractère ( il comprend le 4ème caractère). La raison pour laquelle 3 est égal à la 4ème position est parce que Python commence à 0. Ensuite, lorsque je mets Word [-1:] , cela signifie le deuxième dernier caractère à la fin (les deux points sont derrière le nombre). Mettre -1 fera que Python compte à partir du dernier caractère, plutôt que du premier. Encore une fois, Python commencera à 0. Ainsi, Word [-1:] signifie fondamentalement 'du dernier dernier caractère à la fin de la chaîne.

Ainsi, en coupant les caractères avant le personnage que je veux supprimer et les personnages après et en les prenant en sandwich, je peux supprimer le caractère indésirable. Pensez-y comme une saucisse. Au milieu c'est sale, donc je veux m'en débarrasser. Je coupe simplement les deux bouts que je veux, puis je les assemble sans la partie indésirable au milieu. 

Si je veux supprimer plusieurs caractères consécutifs, je décale simplement les chiffres dans la partie [] (découpage en tranches). Ou si je veux supprimer plusieurs personnages de différentes positions, je peux simplement prendre plusieurs tranches en même temps.

Exemples:

 words = "control"
 removed = "%s%s" % (words[:2], words[-2:])

enlevé est égal à 'cool'.

words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])

enlevé est égal à 'macs'.

Dans ce cas, [3: 5] signifie un caractère à position 3 à travers un caractère à position 5 (à l'exclusion du caractère à la position finale). 

Rappelez-vous, Python commence à compter à 0, vous devrez donc également le faire.

1
oisinvg

Vous pouvez utiliser le remplacement de l'expression régulière du module re. L'utilisation de l'expression ^ vous permet de choisir exactement ce que vous voulez dans votre chaîne.

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

La sortie vers ceci serait "Thisisabsurd". Seules les choses spécifiées après le symbole ^ apparaîtront.

0
Shreyas Rajesh

En dessous de un .. sans utiliser le concept d'expression régulière .. 

ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring
0
Sadheesh

Même l'approche ci-dessous fonctionne

line = "a,b,c,d,e"
alpha = list(line)
        while ',' in alpha:
            alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)

sortie >> abcde

0
M2skills

vous pouvez utiliser set

    charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
    return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])
0
Xu Zhenlei

En Python 3.5

par exemple.,

os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))

Pour supprimer tout le numéro de la chaîne 

0
BonieSV

Scission récursive: s = chaîne; chars = caractères à supprimer

def strip(s,chars):
if len(s)==1:
    return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) +  strip(s[int(len(s)/2):len(s)],chars)

exemple: 

print(strip("Hello!","lo"))    #He!
0
matt

# pour chaque fichier d'un répertoire, renommez le nom du fichier

   file_list = os.listdir (r"D:\Dev\Python")

   for file_name in file_list:

       os.rename(file_name, re.sub(r'\d+','',file_name))
0
Robert Silva

Essaye celui-là:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

Cette méthode fonctionne bien en python 3.5.2

0
Joseph Lee