247

How can I check if a string has several specific characters in it using Python 2?

For example, given the following string:

The criminals stole $1,000,000 in jewels.

How do I detect if it has dollar signs ("$"), commas (","), and numbers?

Jesuisme
  • 1,805
  • 1
  • 31
  • 41
The Woo
  • 17,809
  • 26
  • 57
  • 71
  • 1
    Does that mean every character is supposed to be one of these, or does it suffice that one (or all) of these characters is present in the string? Do they have to be in some order (eg: $2,00) for it be valid? – NullUserException Mar 04 '11 at 02:11
  • 3
    Just as a different sort of approach, `not set(p).isdisjoint(set("0123456789$,"))` where `p` is the string to test. – Kevin May 31 '15 at 03:51
  • Does this answer your question? [Does Python have a string 'contains' substring method?](https://stackoverflow.com/questions/3437059/does-python-have-a-string-contains-substring-method) – wjandrea Dec 08 '21 at 23:47

9 Answers9

341

Assuming your string is 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

And so on for other characters.

... or

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

... or

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

[Edit: added the '$' in s answers]

dappawit
  • 12,182
  • 2
  • 32
  • 26
  • 24
    `s.find('$')!=-1` => `'$' in s` :-) – Jochen Ritzel Mar 04 '11 at 02:25
  • Is there any particular reason why value on not found was kept -1 and not 0 ?? – akki Apr 12 '14 at 19:16
  • 2
    @akki not found is -1 because 0 is the index of the first character in a string. Thus "abc".find('a') = 0. It would be ambiguous if 0 was also the not found value. – lemiant Apr 17 '14 at 14:54
  • ok.I thought the function just checks if a character is in a string and returns some boolean value, guess the function does much much more than that..Thanks. – akki Apr 17 '14 at 17:43
  • 1
    I like that last version using `any()`. Is there a way to refer to the found character `c` in a pythonic style (it seems to be scoped inside of `any()` only), or would I need to make the search for several characters more explicit? – Jens Oct 07 '14 at 00:02
  • 4
    The second example is broken: The regex needs to have brackets `r'[\d\$,]'` so it matches any of those characters, and the `else:` is missing the colon on the end. – bjnord Mar 10 '17 at 22:51
  • if you are using the third option (with set) and your original string is unicode, be sure to use unicode characters as well – alejandro Jul 19 '19 at 01:51
34

user Jochen Ritzel said this in a comment to an answer to this question from user dappawit. It should work:

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

'1', '2', etc. should be replaced with the characters you are looking for.

See this page in the Python 2.7 documentation for some information on strings, including about using the in operator for substring tests.

Update: This does the same job as my above suggestion with less repetition:

# 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
  • 3,088
  • 3
  • 27
  • 24
  • +1 this is more compact than multiple .find()'s, and is fine as long as the number of characters searched for is low. Doesn't need the parentheses though. – Sean Feb 15 '13 at 08:46
  • 1
    @Sean About the parenthenses: I know, however it is easier for me to always use them, than to always remember the precedence order :-). – Abbafei Feb 17 '13 at 07:46
16

Quick comparison of timings in response to the post by 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))

Output:

Func1 Time: 0.0737484362111
Func2 Time: 0.0125144964371

So the code is more compact with any, but faster with the conditional.


EDIT : TL;DR -- For long strings, if-then is still much faster than any!

I decided to compare the timing for a long random string based on some of the valid points raised in the comments:

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

Output:

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

If-then is almost an order of magnitude faster than any!

Jesuisme
  • 1,805
  • 1
  • 31
  • 41
  • 1
    Anyone able to explain why the conditional is that much faster than using any? – Josh Oct 14 '18 at 02:04
  • @Josh probably it's because its simpler. Func1 uses exploded list comprehension so its automatically waaay more complex for simple things. But for 1000 chars, it may well be faster to use Func1 – Hack5 Sep 26 '19 at 19:10
  • This is very misleading. The performance difference is due to the hit in setting up the generator expression for any(). Increasing the string size to 2000 does almost nothing since it will almost always find an 'L' character within the first 256 characters of a random string. If you were to add 2000 spaces in front the difference would be much less. – user5541269 Mar 01 '20 at 20:46
6

This will test if strings are made up of some combination or digits, the dollar sign, and a commas. Is that what you're looking for?

import re

s1 = 'Testing string'
s2 = '1234,12345$'

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

if ( regex.match(s1) ):
   print "s1 matched"
else:
   print "s1 didn't match"

if ( regex.match(s2) ):
   print "s2 matched"
else:
   print "s2 didn't match"
ajwood
  • 18,227
  • 15
  • 61
  • 104
4

My simple, simple, simple approach! =D

Code

string_to_test = "The criminals stole $1,000,000 in jewels."
chars_to_check = ["$", ",", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
for char in chars_to_check:
    if char in string_to_test:
        print("Char \"" + char + "\" detected!")

Output

Char "$" detected!
Char "," detected!
Char "0" detected!
Char "1" detected!
bad_coder
  • 11,289
  • 20
  • 44
  • 72
Eduardo Lucio
  • 1,771
  • 2
  • 25
  • 43
1

Check if chars are in String:

parse_string = lambda chars, string: [char in string for char in chars]

example:

parse_string('$,x', 'The criminals stole $1,000,000 in ....') 

or

parse_string(['$', ',', 'x'], '..minals stole $1,000,000 i..')

output: [True, True, False]

Felix
  • 21
  • 2
0

Another approach, perhaps pythonic, is this:

aString = """The criminals stole $1,000,000 in jewels."""
#
if any(list(map(lambda char: char in aString, '0123456789,$')))
   print(True) # Do something.
NYCeyes
  • 5,215
  • 6
  • 57
  • 64
0

Replace alphanumerics, spaces, hyphens and full-stops by a blank and then count the number of remaining characters:

import re
s = 'hello%world/'
specialCharacters = re.sub('[a-zA-Z0-9-\s\.()]',','',s)
print( "Special Characters:", specialCharacters )
print( "Length:", len( specialCharacters ) )

and the result is:

Special Characters: $/
Length: 2

and then you can just extend the regular expression if for instance you want to include quotes or questions marks as normal characters.

Eamonn Kenny
  • 1,926
  • 18
  • 20
-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")
RF1991
  • 2,037
  • 4
  • 8
  • 17
Nagaraj
  • 668
  • 2
  • 6
  • 8
  • 1
    Could you please provide a bit more context to your answer. – brass monkey Aug 21 '18 at 15:58
  • 1
    checking type of characters present in a string : isalnum(): Returns True if all characters are alphanumeric( a to z , A to Z ,0 to9 ) isalpha(): Returns True if all characters are only alphabet symbols(a to z,A to Z) , isdigit(): Returns True if all characters are digits only( 0 to 9) islower(): Returns True if all characters are lower case alphabet symbols isupper(): Returns True if all characters are upper case aplhabet symbols istitle(): Returns True if string is in title case isspace(): Returns True if string contains only spaces @LazerBass – Nagaraj Aug 21 '18 at 17:06