Jak sprawdzić ciąg znaków pod kątem określonych znaków? [Zamknięte]

182

Jak mogę sprawdzić, czy ciąg zawiera kilka określonych znaków za pomocą Python 2?

Na przykład, biorąc pod uwagę następujący ciąg:

Przestępcy ukradli 1 000 000 $ w klejnotach.

Jak wykryć, czy ma znaki dolara („$”), przecinki („,”) i cyfry?

Woo
źródło
1
Czy to oznacza, że ​​każdy znak powinien być jednym z nich, czy wystarczy, że jeden (lub wszystkie) z tych znaków jest obecny w ciągu? Czy muszą być w jakiejś kolejności (np. 2,00 $), aby były ważne?
NullUserException
2
Podobnie jak inne podejście, not set(p).isdisjoint(set("0123456789$,"))gdzie pjest ciąg do przetestowania.
Kevin

Odpowiedzi:

265

Zakładając, że Twój ciąg znaków to 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

I tak dalej dla innych postaci.

... lub

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

... lub

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

[Edytuj: dodano '$' in sodpowiedzi]

dappawit
źródło
20
s.find('$')!=-1=> '$' in s:-)
Jochen Ritzel
Czy istnieje jakiś szczególny powód, dla którego wartość parametru „nie znaleziono” została zachowana -1, a nie 0?
akki
2
@akki nie znaleziono wynosi -1, ponieważ 0 jest indeksem pierwszego znaku w ciągu. Zatem „abc” .find ('a') = 0. Byłoby dwuznaczne, gdyby 0 również nie było wartością znalezioną.
lemiant
1
Podoba mi się ta ostatnia wersja any(). Czy istnieje sposób odwoływania się do znalezionej postaci cw stylu pythonowym (wydaje się, że ma ona any()jedynie zakres wewnątrz ), czy też muszę bardziej uwydatnić wyszukiwanie kilku znaków?
Jens
3
Drugi przykład jest zepsuty: wyrażenie regularne musi zawierać nawiasy kwadratowe, aby pasowało do r'[\d\$,]'któregokolwiek z tych znaków, a na końcu else:brakuje dwukropka.
bjnord,
23

użytkownik Jochen Ritzel powiedział to w komentarzu do odpowiedzi na to pytanie od użytkownika dappawit. Powinno działać:

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

„1”, „2” itp. Należy zastąpić poszukiwanymi znakami.

Zobacz tę stronę w dokumentacji Python 2.7, aby uzyskać informacje na temat ciągów, w tym na temat używania inoperatora do testów podciągów.

Aktualizacja: wykonuje to samo zadanie, co moja powyższa sugestia, przy mniejszej liczbie powtórzeń:

# 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
źródło
+1 to jest bardziej kompaktowy niż wiele .find () i jest w porządku, o ile liczba szukanych znaków jest niska. Nie potrzebuje jednak nawiasów.
Sean
1
@Sean O nawiasach: Wiem jednak, że łatwiej jest mi zawsze z nich korzystać, niż zawsze pamiętać kolejność pierwszeństwa :-).
Abbafei,
11

Szybkie porównanie czasów w odpowiedzi na post 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))

Wynik:

Func1 Time: 0.0737484362111
Func2 Time: 0.0125144964371

Więc kod jest bardziej kompaktowy z dowolnym, ale szybszy z warunkowym.


EDYCJA: TL; DR - W przypadku długich łańcuchów, jeśli-to jest nadal znacznie szybsze niż jakiekolwiek!

Postanowiłem porównać czas dla długiego losowego ciągu na podstawie niektórych ważnych punktów podniesionych w komentarzach:

# 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))

Wynik:

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

Jeśli-to jest prawie o rząd wielkości szybszy niż jakikolwiek!

Jesuisme
źródło
1
dokładnie to, co chciałem wiedzieć :-)
Lars
1
Czy ktoś jest w stanie wyjaśnić, dlaczego warunkowe jest o wiele szybsze niż użycie dowolnego?
Josh
@Josh prawdopodobnie dlatego, że jest to prostsze. Func1 korzysta ze zrozumienia listy rozstrzelonej, więc automatycznie staje się bardziej skomplikowana dla prostych rzeczy. Ale dla 1000 znaków może być szybsze użycie Func1
Hack5
@ Hack5 załóżmy, że phraseciąg z alfabetami od A do Z i chcę wydrukować, które alfabety nie występują razem, ciąg będzie any()lepszy? czy jest jakiś krótki sposób na sprawdzenie?
Avishek Datta Ray
@ Barefaced Bare na tym poziomie, wybierz, który z nich wygląda ładniej. Szybkość prawdopodobnie nie ma znaczenia, chyba że kontrolujesz nukleary (w takim przypadku nie powinieneś używać Pythona)
Hack5
5

To sprawdzi, czy ciągi znaków składają się z kombinacji lub cyfr, znaku dolara i przecinków. Czy tego szukasz?

import re

s1 = „Testowanie ciągu”
s2 = „1234,12345 $”

regex = re.compile („[0–9, $] + $”)

if (regex.match (s1)):
   drukuj „s1 dopasowane”
jeszcze:
   print „s1 nie pasuje”

if (regex.match (s2)):
   drukuj „s2 dopasowane”
jeszcze:
   print „s2 nie pasuje”
ajwood
źródło
Nie musisz uciekać przed $, jeśli jest w klasie postaci. To również pasuje 'testing $tring', co nie wydaje mi się, że OP chce się wydarzyć.
NullUserException
Jeśli dobrze pamiętam, nie pasuje do 'testing $tring'niego, jeśli matchmetoda jest używana, tylko jeśli searchjest używana. Myślę więc, że jego kod jest w porządku.
dappawit
@dappa Będzie on nadal pasuje '$string'choć
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 („Non Space Special Character”)

Nagaraj
źródło
1
Czy możesz podać nieco więcej kontekstu do swojej odpowiedzi.
mosiężna małpa
sprawdzanie typu znaków obecnych w ciągu: isalnum (): Zwraca True, jeśli wszystkie znaki są alfanumeryczne (od a do z, A do Z, 0 do 9) isalpha (): Zwraca True, jeśli wszystkie znaki są tylko symbolami alfabetu (od a do z, A do Z), isdigit (): Zwraca True, jeśli wszystkie znaki są tylko cyframi (od 0 do 9) islower (): Zwraca True, jeśli wszystkie znaki są symbolami małych liter isupper (): Zwraca True, jeśli wszystkie znaki są symbolami wielkich liter istitle (): Zwraca True, jeśli ciąg znaków jest w tytule, isspace (): Zwraca True, jeśli ciąg znaków zawiera tylko spacje @LazerBass
Nagaraj