Finding letters in a string

Question:

I’m trying to write a code that finds the letters in a string containing special characters, numbers and letters. The following code returns nothing:

a ="&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
print(a)
final = a.split()
for y in final:
    if (y.isalpha == True):
        print(y)

Output: &&)&gokjhohgouigougyy^&*^x
=> None

Can someone tell me what is the issue and how can I do it without using the re.findall, e.g. using loops like:

for(y in final):
    if (ord(y) in range (97, 127)):
        print(y)

The above code works:

for y in a:
    if (ord(y) in range (97, 127)):
        print(y, end='')
Asked By: novice2020

||

Answers:

You need to call y.isalpha as y.isalpha() this is because isalpha is a function or method.

>>> y='y'
>>> y.isalpha
<built-in method isalpha of str object at 0x00FA3A40>
>>> y.isalpha()
True

Note that your split will give you words not letters – which may not be what you are expecting:

>>> s = "Yes! These are words."
>>> for w in s.split(' '):
...    print(w, w.isalpha())
...
Yes! False
These True
are True
words. False
>>>

One of the things to get used to in python is the difference between a property and a method – a property is something that you can read a method performs some action – dir lists both so for a string s you have:

>>> dir(s)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__',
 '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', 
 '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__',
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__',
 '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 
 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum',
 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 
 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join',
 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind',
 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'
]

Where:

>>> s.__class__
<class 'str'>

is a property and:

>>> s.capitalize
<built-in method capitalize of str object at 0x03529F50>

is a method and needs to be called by the addition of parenthesis () to actually perform their function. It is worth also distinguishing between methods that return a value and those that operate in place.

>>> s.lower()
'yes! these are words.'

Returns a value as does s.split() but sort is an in-place operation, e.g.:

>>> words = s.lower().split()
>>> words
['yes!', 'these', 'are', 'words.']
>>> words.sort()
>>> words
['are', 'these', 'words.', 'yes!']
>>>
Answered By: Steve Barnes

You don’t need to split it up and you should call isalpha as isalpha() instead because they are different things. This should print all the letters in what i assume is the format you want.

a ="&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
print(a)

for y in a:
    if y.isalpha():
        print(y)
Answered By: pimmen

Splitting a string returns a list of substrings. For example: “abc def ghi”.split(” “) returns [“abc”, “def”, “ghi”].
You needn’t split the string for what you’re trying. Just loop over the string itself.

string = "&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
for char in string:
    if char.isalpha():
        print(char)
Answered By: rohithpr

From your code it looks more like you want to remove unwanted characters from the string, rather than find those to retain.

So, if you want to print the result:

a ="&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
for c in a:
    if c.isalpha():
        print(c)

Output:

g
o
k
...
y
y
x

But usually you would want to assign the filtered string to a variable, like this which combines a generator comprehension with the join() string function:

a ="&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
s = ''.join(c for c in a if c.isalpha())
print(s)

Output:

gokjhohgouigougyyx

Answered By: mhawke

If you want a list use a list comprehension:

print([ch for ch in a if ch.isalpha()])
['g', 'o', 'k', 'j', 'h', 'o', 'h', 'g', 'o', 'u', 'i', 'g', 'o', 'u', 'g', 'y', 'y', 'x']

If you want to remove punctuation, digits and spaces from the string you can use str.translate:

from string import punctuation, digits

tbl = str.maketrans({ord(ch):"" for ch in punctuation+digits+" "})

print(a.translate(tbl))

gokjhohgouigougyyx

The tbl is just the ord of each character we want to replace with the value we want to replace it with which in this case is an empty string.

Answered By: Padraic Cunningham

If you would like to get clever you could also look at using a filter object:

>>> def isalpha(c):
...    """ Check if a character is a member of the alphabet """
...    return c.isalpha()
...
>>> s = "This string, or sentence, should have __no__ non-alphabetic characters in it!"
>>> f = filter(isalpha, s)
>>> ''.join(f)
'Thisstringorsentenceshouldhavenononalphabeticcharactersinit'

This can be shortened to:

>>> s="This string, or sentence, should have __no__ non-alphabetic characters in it!"
>>> ''.join(filter(lambda a: a.isalpha(), s))
'Thisstringorsentenceshouldhavenononalphabeticcharactersinit'
>>>
Answered By: Steve Barnes

Hope this helps:

a = "&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
for character in a:
    if character.isalpha():
        print(character)

If you also wanted to count the letters, you could do it using a dictionary and a list:

di = dict()
a = "&*&)*&GOKJHOHGOUIGougyY^&*^x".lower()
for character in a:
    if character.isalpha():
        di[character] = di.get(character,0) + 1

lst = sorted([(v,k) for k,v in di.items()], reverse=True)
for v, k in lst:
    print(k, v)

That should print the letters in decreasing order of frequency.

Answered By: rnzoluna
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.