Is there an way to range over characters? something like this.
for c in xrange( 'a', 'z' ):
print c
I hope you guys can help.
This is a great use for a custom generator:
Python 2:
def char_range(c1, c2):
"""Generates the characters from `c1` to `c2`, inclusive."""
for c in xrange(ord(c1), ord(c2)+1):
yield chr(c)
then:
for c in char_range('a', 'z'):
print c
Python 3:
def char_range(c1, c2):
"""Generates the characters from `c1` to `c2`, inclusive."""
for c in range(ord(c1), ord(c2)+1):
yield chr(c)
then:
for c in char_range('a', 'z'):
print(c)
import string
for char in string.ascii_lowercase:
print char
See string constants for the other possibilities, including uppercase, numbers, locale-dependent characters, all of which you can join together like string.ascii_uppercase + string.ascii_lowercase if you want all of the characters in multiple sets.
You have to convert the characters to numbers and back again.
for c in xrange(ord('a'), ord('z')+1):
print chr(c) # resp. print unicode(c)
For the sake of beauty and readability, you can wrap this in a generator:
def character_range(a, b, inclusive=False):
back = chr
if isinstance(a,unicode) or isinstance(b,unicode):
back = unicode
for c in xrange(ord(a), ord(b) + int(bool(inclusive)))
yield back(c)
for c in character_range('a', 'z', inclusive=True):
print(chr(c))
This generator can be called with inclusive=False (default) to imitate Python's usual bhehaviour to exclude the end element, or with inclusive=True (default) to include it. So with the default inclusive=False, 'a', 'z' would just span the range from a to y, excluding z.
If any of a, b are unicode, it returns the result in unicode, otherwise it uses chr.
It currently (probably) only works in Py2.
There are other good answers here (personally I'd probably use string.lowercase), but for the sake of completeness, you could use map() and chr() on the lower case ascii values:
for c in map(chr, xrange(97, 123)):
print c
If you have a short fixed list of characters, just use Python's treatment of strings as lists.
for x in 'abcd':
print x
or
[x for x in 'abcd']
I like an approach which looks like this:
base64chars = list(chars('AZ', 'az', '09', '++', '//'))
It certainly can be implemented with a lot of more comfort, but it is quick and easy and very readable.
Python 3
Generator version:
def chars(*args):
for a in args:
for i in range(ord(a[0]), ord(a[1])+1):
yield chr(i)
Or, if you like list comprehensions:
def chars(*args):
return [chr(i) for a in args for i in range(ord(a[0]), ord(a[1])+1)]
The first yields:
print(chars('ĀĈ'))
<generator object chars at 0x7efcb4e72308>
print(list(chars('ĀĈ')))
['Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ']
while the second yields:
print(chars('ĀĈ'))
['Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ']
It is really convenient:
base64chars = list(chars('AZ', 'az', '09', '++', '//'))
for a in base64chars:
print(repr(a),end='')
print('')
for a in base64chars:
print(repr(a),end=' ')
outputs
'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P''Q''R''S''T''U''V''W''X''Y''Z''a''b''c''d''e''f''g''h''i''j''k''l''m''n''o''p''q''r''s''t''u''v''w''x''y''z''0''1''2''3''4''5''6''7''8''9''+''/'
'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '+' '/'
Why the list()? Without base64chars might become a generator (depending on the implementation you chose) and thus can only be used in the very first loop.
Python 2
Similar can be archived with Python 2. But it is far more complex if you want to support Unicode, too. To encourage you to stop using Python 2 in favor of Python 3 I do not bother to provide a Python 2 solution here ;)
Try to avoid Python 2 today for new projects. Also try to port old projects to Python 3 first before extending them - in the long run it will be worth the effort!
Proper handling of Unicode in Python 2 is extremely complex, and it is nearly impossible to add Unicode support to Python 2 projects if this support was not build in from the beginning.
Hints how to backport this to Python 2:
Use xrange instead of range
Create a 2nd function (unicodes?) for handling of Unicode:
Use unichr instead of chr to return unicode instead of str
Never forget to feed unicode strings as args to make ord and array subscript work properly
for character in map( chr, xrange( ord('a'), ord('c')+1 ) ):
print character
prints:
a
b
c
# generating 'a to z' small_chars.
small_chars = [chr(item) for item in range(ord('a'), ord('z')+1)]
# generating 'A to Z' upper chars.
upper_chars = [chr(item).upper() for item in range(ord('a'), ord('z')+1)]
For Uppercase Letters:
for i in range(ord('A'), ord('Z')+1):
print(chr(i))
For Lowercase letters:
for i in range(ord('a'), ord('z')+1):
print(chr(i))
Inspired from the top post above, I came up with this :
map(chr,range(ord('a'),ord('z')+1))
Using #ned-batchelder's answer here, I'm amending it a bit for python3
def char_range(c1, c2):
"""Generates the characters from `c1` to `c2`, inclusive."""
"""Using range instead of xrange as xrange is deprecated in Python3"""
for c in range(ord(c1), ord(c2)+1):
yield chr(c)
Then same thing as in Ned's answer:
for c in char_range('a', 'z'):
print c
Thanks Ned!
i had the same need and i used this :
chars = string.ascii_lowercase
range = list(chars)[chars.find('a'):chars.find('k')+1]
Hope this will Help Someone
Use "for count in range" and chr&ord:
print [chr(ord('a')+i) for i in range(ord('z')-ord('a'))]
Use list comprehension:
for c in [chr(x) for x in range(ord('a'), ord('z'))]:
print c
Another option (operates like range - add 1 to stop if you want stop to be inclusive)
>>> import string
>>> def crange(arg, *args):
... """character range, crange(stop) or crange(start, stop[, step])"""
... if len(args):
... start = string.ascii_letters.index(arg)
... stop = string.ascii_letters.index(args[0])
... else:
... start = string.ascii_letters.index('a')
... stop = string.ascii_letters.index(arg)
... step = 1 if len(args) < 2 else args[1]
... for index in range(start, stop, step):
... yield string.ascii_letters[index]
...
>>> [_ for _ in crange('d')]
['a', 'b', 'c']
>>>
>>> [_ for _ in crange('d', 'g')]
['d', 'e', 'f']
>>>
>>> [_ for _ in crange('d', 'v', 3)]
['d', 'g', 'j', 'm', 'p', 's']
>>>
>>> [_ for _ in crange('A', 'G')]
['A', 'B', 'C', 'D', 'E', 'F']
Depending on how complex the range of characters is, a regular expression may be convenient:
import re
import string
re.findall("[a-f]", string.printable)
# --> ['a', 'b', 'c', 'd', 'e', 'f']
re.findall("[n-qN-Q]", string.printable)
# --> ['n', 'o', 'p', 'q', 'N', 'O', 'P', 'Q']
This works around the pesky issue of accidentally including the punctuation characters in between numbers, uppercase and lowercase letters in the ASCII table.
Related
My purpose is to get an input as a string and return a list of lower case letters of that string, without repeats, without punctuations, in alphabetical order. For example, the input "happy!" would get ['a','h','p','y']. I try to use the join function to get rid of my punctuations but somehow it doesn't work. Does anybody know why? Also, can sort.() sort alphabets? Am I using it in the right way? Thanks!
def split(a):
a.lower()
return [char for char in a]
def f(a):
i=split(a)
s=set(i)
l=list(s)
v=l.join(u for u in l if u not in ("?", ".", ";", ":", "!"))
v.sort()
return v
.join() is a string method, but being used on a list, so the code raises an exception, but join and isn't really needed here.
You're on the right track with set(). It only stores unique items, so create a set of your input and compute the intersection(&) with lower case letters. Sort the result:
>>> import string
>>> s = 'Happy!'
>>> sorted(set(s.lower()) & set(string.ascii_lowercase))
['a', 'h', 'p', 'y']
You could use:
def f(a):
return sorted(set(a.lower().strip('?.;:!')))
>>> f('Happy!')
['a', 'h', 'p', 'y']
You could also use regex for this:
pattern = re.compile(r'[^a-z]')
string = 'Hello# W0rld!!##'
print(sorted(set(pattern.sub('', string))))
Output:
['d', 'e', 'l', 'o', 'r']
I have a list lets say:
DIRECTION_LETTERS=['u', 'd' ,'r' , 'l', 'w', 'x', 'y', 'z']
Now the other parameter of mine is like arguement, I write in
udl and it returns ['udl']
so lets say another list arg_list = ['udl']
I want to check if u and d and l is in this list or i want to check if none of the letters in my direction letters list in the arg list
to make it print error msg I have tried this:
for letter in DIRECTION_LETTERS:
for char in arg_list[4]:
if letter in arg_list[4][0]:
continue
else:
print (ERROR_MESSAGE_DIRECTIONS)
return False
return True
There's a handy function in Python called all() which returns true if all arguments are true. Feel free to find a nice way of using it, but in general:
>>> DIRECTION_LETTERS=['u', 'd' ,'r' , 'l', 'w', 'x', 'y', 'z']
>>>
>>> s="udl"
>>> print(all(c in DIRECTION_LETTERS for c in s))
True
>>> s="udlxa"
>>> print(all(c in DIRECTION_LETTERS for c in s))
False
This line
if letter in arg_list[4][0]:
needs to be
if char in DIRECTION_LETTERS:
and you need to delete the line for letter in DIRECTION_LETTERS:.
I have put the letters a-z in a list. How would I find the value of an item in the list depending on what the user typed?
For example if they type the letter a it would return c, f would return h and x would return z.
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
newletters = []
offset = 2
userInput = input('type a string')
newvalue = chr(ord(userInput)+offset)
split = list(newvalue)
print split
the above works for a character but not for a string..help?!
You can try this:
>>> offset = 2
>>> aString = raw_input("digit a letter: ")
>>> aString
'a'
>>> chr(ord(aString)+offset)
'c'
documentation:
https://docs.python.org/2/library/functions.html#chr
https://docs.python.org/2/library/functions.html#ord
If you want to iterate over an entire string, a simple way is using a for loop. I assume the input string is always lowercase.
EDIT2: I improved the solution to handle the case when a letter is 'y' or 'z' and without "rotation" should begin a not alphabetic character, eg:
# with only offset addiction this return a non-alphabetic character
>>> chr(ord('z')+2)
'|'
# the 'z' rotation return the letter 'b'
>>> letter = "z"
>>> ord_letter = ord(letter)+offset
>>> ord_letter_rotated = ((ord_letter - 97) % 26) + 97
>>> chr(ord_letter_rotated)
'b'
The code solution:
offset = 2
aString = raw_input("digit the string to convert: ")
#aString = "abz"
newString = ""
for letter in aString:
ord_letter = ord(letter)+offset
ord_letter_rotated = ((ord_letter - 97) % 26) + 97
newString += chr(ord_letter_rotated)
print newString
The output of this code for the entire lowercase alphabet:
cdefghijklmnopqrstuvwxyzab
Note: you can obtain the lowercase alphabet for free also this way:
>>> import string
>>> string.lowercase
'abcdefghijklmnopqrstuvwxyz'
See the wikipedia page to learn something about ROT13:
https://en.wikipedia.org/wiki/ROT13
What should happen for z? Should it become b?
You can use Python's maketrans and translate functions to do this as follows:
import string
def rotate(text, by):
s_from = string.ascii_lowercase
s_to = string.ascii_lowercase[by:] + string.ascii_lowercase[:by]
cypher_table = string.maketrans(s_from, s_to)
return text.translate(cypher_table)
user_input = raw_input('type a string: ').lower()
print rotate(user_input, 2)
This works on the whole string as follows:
type a string: abcxyz
cdezab
How does it work?
If you print s_from and s_to they look as follows:
abcdefghijklmnopqrstuvwxyz
cdefghijklmnopqrstuvwxyzab
maketrans creates a mapping table to map characters in s_from to s_to. translate then applies this mapping to your string.
Define a function named encrypt which takes as input a string (which is the name of a text file in the current directory). The function should then print the encrypted content of this file.
Here text encryption is done by replacing every occurence of a vowel with its next in the list 'aeiou'. So 'a' is replaced by 'e', 'e' is replaced by 'i', so on and 'u' is replaced by 'a'. Also each consonant is replaced with its next in the list 'bcdfghjklmnpqrstvwxyz' so 'b' is replaced by 'c', 'c' by 'd' so on and lastly 'z' is replaced by 'b'. The same replacement logic holds for upper case letters. Note that non-alphabetic characters should appear in their original form without modification.
def encrypt (eo):
vowel = 'aeiou'
con = 'bcdfghjklmnpqrstvwxyz'
for eo in vowel (t[i+1]):
res=
return res
This piece of code could be useful. Pay attention to the vowel and con content. I appended one letter in each variable vowel and com to avoid the modulo operation. Assume the eo is the input string.
def encrypt (eo):
vowel = 'aeioua'
con = 'bcdfghjklmnpqrstvwxyzb'
encrytTable = vowel + con
res = ""
for letter in eo:
res += encrytTable[encrytTable.find(letter)+1]
return res
If eo is the input filename, you need some file read operation like:
>>> fh = open(eo)
>>> fh.read()
>>> fh.>>> fh.close()
And a more effient way to do it, is pre-compute a encryptTable array and use the table to replace the origianl input in a linear manner. In following code, I assume your input only include lower-case letters. Abd if the shift distance is not 1, you need to modify the code. Pre-compute:
>>> vowel = 'aeioua'
>>> con = 'bcdfghjklmnpqrstvwxyzb'
>>> encryptTable = []
>>> for i in xrange(97,123):
temp = chr(i)
if temp in vowel:
encryptTable.append(vowel[vowel.find(temp)+1])
else:
encryptTable.append(con[con.find(temp)+1])
>>> encryptTable
['e', 'c', 'd', 'f', 'i', 'g', 'h', 'j', 'o', 'k', 'l', 'm', 'n', 'p', 'u', 'q', 'r', 's', 't', 'v', 'a', 'w', 'x', 'y', 'z', 'b']
And then replace the content:
>>> plain = "helloworld"
>>> encrypted = "".join([encryptTable[ord(i)-ord('a')] for i in plain])
>>> encrypted
'jimmuxusmf'
def encrypt(s):
vowels = 'aeiou'
vowelReps = dict(zip(vowels, vowels[1:]+vowels[0]))
cons = 'bcdfghjklmnpqrstvwxyz'
consReps = dict(zip(cons, cons[1:]+cons[0]))
answer = []
for char in s:
if char.lower() in vowelReps:
answer.append(vowelReps[char.lower()]
else:
answer.append(consReps[char.lower()]
if char.isupper():
answer[-1] = answer[-1].upper()
return ''.join(answer)
You have multiple problems here:
for eo in ... would replace the eo argument; except
t isn't defined, so will give a NameError;
res= is a SyntaxError; and
Even if all of the above was fixed, return res will happen on the first character, as it is indented too far.
Instead, you could do the following:
def encrypt(eo):
vowels = "aeiou"
for index, vowel in enumerate(vowels): # iterate through the five vowels
new_v = vowels[(index + 1) % len(vowels)] # determine replacement
eo = eo.replace(vowel, new_v) # do replacement
You can then do the same thing for the consonants, then return eo (which should be indented to the same level as vowels = ...!).
Note:
the use of % to keep the index into vowels within the appropriate range; and
the use of enumerate to get both the character vowel from the string vowels and its index within that string.
Alternatively, and more efficiently:
build a dictionary mapping character in to character out;
build a list of replacement characters using the input eo and the dict; and
str.join the output characters together and return it.
I have a code in Python and want to find vowels in a string.
The code I have written is following....I tried different combinations for using For-Loop, but it throws two different errors;
'int' object is not iterable,
string indices must be integers, not str.
how can I find all vowels in a line?
str1 = 'sator arepo tenet opera rotas'
vow1 = [str1[i] for i in str1 if str1[i] is 'a' | 'e' | 'o']
what about:
vowels = [ c for c in str1 if c in 'aeo' ]
You're getting errors because when you loop over a string, you loop over the characters in the string (not string indices) and because 'a' | 'e' | 'o' doesn't make sense for strings -- (they don't support the | operator)
>>> str1 = 'sator arepo tenet opera rotas'
>>> vowels = [ c for c in str1 if c in 'aeo' ]
>>> print vowels
['a', 'o', 'a', 'e', 'o', 'e', 'e', 'o', 'e', 'a', 'o', 'a']
One final comment, you shouldn't use is to test for equality. is tests for identity. A simple test:
a = 565
b = 565
print a == b #True
print a is b #False (!)
The reason is because a and b reference different objects that have the same value.
Try this code:
str1 = 'sator arepo tenet opera rotas'
i=0
vowl=''
for char in str1:
if char in 'aeiouAEIOU':
vowl=vowl+char+','
vowl=vowl[:-1]
print (vowl)
The output is:
a,o,a,e,o,e,e,o,e,a,o,a
In [1]: str1 = 'sator arepo tenet opera rotas'
In [2]: filter(lambda x: x in 'aeiou', str1)
Out[2]: 'aoaeoeeoeaoa'