Comment vérifier une chaîne pour des caractères spécifiques?

187

Comment puis-je vérifier si une chaîne contient plusieurs caractères spécifiques en utilisant Python 2?

Par exemple, étant donné la chaîne suivante:

Les criminels ont volé 1 000 000 $ de bijoux.

Comment puis-je détecter s'il comporte des signes dollar ("$"), des virgules (",") et des chiffres?

Le Woo
la source
1
Cela signifie-t-il que chaque caractère est censé être l'un de ceux-ci, ou suffit-il qu'un (ou tous) ces caractères soient présents dans la chaîne? Doivent-ils être dans un certain ordre (par exemple: 2,00 $) pour que cela soit valide?
NullUserException
2
Tout comme une autre sorte d'approche, not set(p).isdisjoint(set("0123456789$,"))pest la chaîne à tester.
Kevin

Réponses:

269

En supposant que votre chaîne est s:

'$' in s        # found
'$' not in s    # not found

# original answer given, but less Pythonic than the above...
s.find('$')==-1 # not found
s.find('$')!=-1 # found

Et ainsi de suite pour les autres personnages.

... ou

pattern = re.compile(r'\d\$,')
if pattern.findall(s):
    print('Found')
else
    print('Not found')

... ou

chars = set('0123456789$,')
if any((c in chars) for c in s):
    print('Found')
else:
    print('Not Found')

[Modifier: a ajouté les '$' in sréponses]

dappawit
la source
21
s.find('$')!=-1=> '$' in s:-)
Jochen Ritzel
Y a-t-il une raison particulière pour laquelle la valeur sur non trouvé a été conservée -1 et non 0?
akki
2
@akki introuvable est -1 car 0 est l'index du premier caractère d'une chaîne. Ainsi "abc" .find ('a') = 0. Ce serait ambigu si 0 était également la valeur non trouvée.
lemiant
1
J'aime cette dernière version en utilisant any(). Existe-t-il un moyen de faire référence au personnage trouvé cdans un style pythonique (il semble être limité à l'intérieur any()seulement), ou devrais-je rendre la recherche de plusieurs caractères plus explicite?
Jens
3
Le deuxième exemple est cassé: le regex doit avoir des crochets r'[\d\$,]'pour qu'il corresponde à l'un de ces caractères, et il else:manque les deux-points à la fin.
bjnord
24

L'utilisateur Jochen Ritzel a répondu dans un commentaire à la réponse à cette question de l'utilisateur dappawit. Cela devrait fonctionner:

('1' in var) and ('2' in var) and ('3' in var) ...

«1», «2», etc. doivent être remplacés par les caractères que vous recherchez.

Consultez cette page dans la documentation Python 2.7 pour obtenir des informations sur les chaînes, notamment sur l'utilisation de l' inopérateur pour les tests de sous-chaînes.

Mise à jour: Cela fait le même travail que ma suggestion ci-dessus avec moins de répétition:

# When looking for single characters, this checks for any of the characters...
# ...since strings are collections of characters
any(i in '<string>' for i in '123')
# any(i in 'a' for i in '123') -> False
# any(i in 'b3' for i in '123') -> True

# And when looking for subsrings
any(i in '<string>' for i in ('11','22','33'))
# any(i in 'hello' for i in ('18','36','613')) -> False
# any(i in '613 mitzvahs' for i in ('18','36','613')) ->True
Abbafei
la source
+1 c'est plus compact que plusieurs .find (), et c'est bien tant que le nombre de caractères recherchés est faible. N'a pas besoin des parenthèses cependant.
Sean
1
@Sean A propos des parenthèses: je sais, cependant il m'est plus facile de toujours les utiliser que de toujours me souvenir de l'ordre de priorité :-).
Abbafei
12

Comparaison rapide des horaires en réponse au message d'Abbafei:

import timeit

def func1():
    phrase = 'Lucky Dog'
    return any(i in 'LD' for i in phrase)

def func2():
    phrase = 'Lucky Dog'
    if ('L' in phrase) or ('D' in phrase):
        return True
    else:
        return False

if __name__ == '__main__': 
    func1_time = timeit.timeit(func1, number=100000)
    func2_time = timeit.timeit(func2, number=100000)
    print('Func1 Time: {0}\nFunc2 Time: {1}'.format(func1_time, func2_time))

Production:

Func1 Time: 0.0737484362111
Func2 Time: 0.0125144964371

Le code est donc plus compact avec n'importe lequel, mais plus rapide avec le conditionnel.


EDIT: TL; DR - Pour les longues chaînes, if-then est toujours beaucoup plus rapide que tout!

J'ai décidé de comparer le timing d'une longue chaîne aléatoire en fonction de certains des points valides soulevés dans les commentaires:

# Tested in Python 2.7.14

import timeit
from string import ascii_letters
from random import choice

def create_random_string(length=1000):
    random_list = [choice(ascii_letters) for x in range(length)]
    return ''.join(random_list)

def function_using_any(phrase):
    return any(i in 'LD' for i in phrase)

def function_using_if_then(phrase):
    if ('L' in phrase) or ('D' in phrase):
        return True
    else:
        return False

if __name__ == '__main__':
    random_string = create_random_string(length=2000)
    func1_time = timeit.timeit(stmt="function_using_any(random_string)",
                               setup="from __main__ import function_using_any, random_string",
                               number=200000)
    func2_time = timeit.timeit(stmt="function_using_if_then(random_string)",
                               setup="from __main__ import function_using_if_then, random_string",
                               number=200000)
    print('Time for function using any: {0}\nTime for function using if-then: {1}'.format(func1_time, func2_time))

Production:

Time for function using any: 0.1342546
Time for function using if-then: 0.0201827

If-then est presque un ordre de grandeur plus rapide que tout!

Jesuisme
la source
1
exactement ce que je voulais savoir :-)
Lars
1
Quelqu'un est-il capable d'expliquer pourquoi le conditionnel est beaucoup plus rapide que d'en utiliser un?
Josh
@Josh c'est probablement parce que c'est plus simple. Func1 utilise la compréhension de liste éclatée, ce qui le rend automatiquement plus complexe pour les choses simples. Mais pour 1000 caractères, il pourrait bien être plus rapide d'utiliser Func1
Hack5
@ Hack5 suppose phrasequ'une chaîne avec des alphabets de A à Z et que je veux imprimer quels alphabets ne sont pas présents ensemble, la chaîne utilisera-t- any()elle mieux? ou y a-t-il un moyen court de vérifier?
Avishek Datta Ray le
@Barefaced Bare à ce genre de niveau, choisissez celui qui vous convient le mieux. La vitesse n'a probablement pas d'importance, à moins que vous ne contrôliez les armes nucléaires (auquel cas vous ne devriez pas utiliser python)
Hack5
5

Cela testera si les chaînes sont constituées d'une combinaison ou de chiffres, du signe dollar et d'une virgule. C'est ça que tu cherches?

importer re

s1 = 'Chaîne de test'
s2 = '1234,12345 $'

regex = re.compile ('[0-9, $] + $')

if (regex.match (s1)):
   imprimer "s1 correspondant"
autre:
   print "s1 ne correspond pas"

if (regex.match (s2)):
   imprimer "s2 correspondant"
autre:
   print "s2 ne correspond pas"
Ajwood
la source
Vous n'avez pas besoin d'échapper au $ s'il se trouve dans une classe de caractères. Cela correspondra également 'testing $tring', ce que je ne pense pas que le PO veut se produire.
NullUserException
Si je me souviens bien, cela ne correspondrait 'testing $tring'pas si la matchméthode est utilisée, seulement si elle searchest utilisée. Donc je pense que son code est bien.
dappawit
@dappa Il correspondra toujours '$string'bien
NullUserException
-2
s=input("Enter any character:")   
if s.isalnum():   
   print("Alpha Numeric Character")   
   if s.isalpha():   
       print("Alphabet character")   
       if s.islower():   
         print("Lower case alphabet character")   
       else:   
         print("Upper case alphabet character")   
   else:   
     print("it is a digit")   
elif s.isspace():   
    print("It is space character")   

else:
print ("Caractère spécial sans espace")

Nagaraj
la source
1
Pourriez-vous donner un peu plus de contexte à votre réponse.
brass monkey
vérification du type de caractères présents dans une chaîne: isalnum (): renvoie True si tous les caractères sont alphanumériques (a à z, A à Z, 0 à 9) isalpha (): renvoie True si tous les caractères ne sont que des symboles alphabétiques (a à z, A à Z), isdigit (): renvoie True si tous les caractères sont uniquement des chiffres (0 à 9) islower (): renvoie True si tous les caractères sont des symboles alphabétiques minuscules isupper (): renvoie True si tous les caractères sont des symboles alphabétiques majuscules istitle (): renvoie True si la chaîne est dans la casse du titre isspace (): renvoie True si la chaîne ne contient que des espaces @LazerBass
Nagaraj