73

I'm 90% sure there is a built in function that does this.

I need to find the position of a character in an alphabet. So the character "b" is position 1 (counting from 0), etc. Does anyone know what the function is called?

What I'm trying to do is to send all the characters X amount of "steps" back in the alpha bet, so if I have a string with "hi", it would be "gh" if I send it back one step. There might be a better way of doing it, any tips?

starball
  • 20,030
  • 7
  • 43
  • 238
qwerty
  • 973
  • 2
  • 9
  • 10

7 Answers7

115

It is called index. For e.g.

>>> import string
>>> string.lowercase.index('b')
1
>>> 

Note: in Python 3, string.lowercase has been renamed to string.ascii_lowercase.

Alex Ryan
  • 2,427
  • 2
  • 18
  • 15
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
  • 2
    Thank you! is there any reverse function for that, so if i have the index of a character i can get the actual character? – qwerty May 08 '11 at 11:33
  • 8
    Just `[]` it in the string or list. `>>>string.lowercase[2]` – Senthil Kumaran May 08 '11 at 11:34
  • Thank you! I keep getting an error though, would you mind taking a look at it? I'm new to python, sorry! http://pastebin.com/h0b95sPg, the error is: ValueError: substring not found – qwerty May 08 '11 at 11:46
  • @qwerty, I don't find any problem. It works properly. I thought you meant to do `result += newChar` and it prints `knzcr ne sdws` – Senthil Kumaran May 08 '11 at 11:52
  • Hmm, you're right! It works with the example i posted (if i change it to newChar), but i was using another text myself. I think it doesn't work because i need to skip all of the non-alphabetic characters like !,. etc. I found a method called .isalpha() but it doesn't seem to work either. http://pastebin.com/McvRTq1t – qwerty May 08 '11 at 12:01
  • I just saw that i failed with newChar again, but that's not what's causing the error now. – qwerty May 08 '11 at 12:09
  • 1
    It failed at the point where it tried to index `Y`. It wont be present because it is not a lowercase. instead of `string.lowercase` you can try `string.ascii_letters` – Senthil Kumaran May 08 '11 at 12:12
  • Yep, that did it! I used text.lower() before the loop but it doesn't seem to have worked then!? Thank you! – qwerty May 08 '11 at 12:15
  • 1
    I had to use ```print string.index(string.ascii_lowercase, "c")``` – Victor S Dec 25 '11 at 00:48
  • 3
    Python 3: `string.ascii_lowercase.index( "R".lower() ) # --> 17` – handle Aug 02 '16 at 11:52
  • 1
    This answer fails to mention how it works; "It is called `index`" explains nothing. `string.lowercase` and `string.ascii_lowercase` are pre-initialized string literals containing the lowercase alpha characters in alphabetical order, and `.index('b')` finds the index of the input character in that string. – pigi5 Apr 06 '21 at 16:37
51

Without the import

def char_position(letter):
    return ord(letter) - 97

def pos_to_char(pos):
    return chr(pos + 97)
Jakob Bowyer
  • 33,878
  • 8
  • 76
  • 91
4

You can use ord() to get a character's ASCII position, and chr() to convert a ASCII position into a character.

EDIT: Updated to wrap alphabet so a-1 maps to z and z+1 maps to a

For example:

my_string  = "zebra"
difference = -1
new_string = ''.join((chr(97+(ord(letter)-97+difference) % 26) for letter in my_string))

This will create a string with all the characters moved one space backwards in the alphabet ('ydaqz'). It will only work for lowercase words.

Peter Collingridge
  • 10,849
  • 3
  • 44
  • 61
  • Awesome, i think this is the method i was trying to remember. This is so getting bookmarked! – qwerty May 08 '11 at 12:03
  • 1
    You may want to note that this does not loop a<->z, and similarly for the uppercase varieties. Assuming that qwerty is aiming for some sort of ROT algorithm, fixing that upper with the help of a modulo operation (or two) would be needed. – Stigma May 08 '11 at 12:07
  • That's a fair point. It will also do weird things to spaces and punctuation. I assume the same is true of the accepted answer. – Peter Collingridge May 08 '11 at 22:01
  • I've update my answer to wrap the alphabet. I'm going to assume the string has been converted to lowercase first. – Peter Collingridge May 08 '11 at 22:36
2
# define an alphabet
alfa = "abcdefghijklmnopqrstuvwxyz"

# define reverse lookup dict
rdict = dict([ (x[1],x[0]) for x in enumerate(alfa) ])

print alfa[1] # should print b

print rdict["b"] # should print 1

rdict is a dictionary that is created by stepping through the alphabet, one character at a time. The enumerate function returns a tuple with the list index, and the character. We reverse the order by creating a new tuple with this code: ( x[1], x[0]) and then turn the list of tuples into a dictionary. Since a dictionary is a hash table (key, value) data structure, we can now look up the index of any alphabet character.

However, that is not what you want to solve your problem, and if this is a class assignment you would probably get 0 for plagiarism if you submit it. For encoding the strings, first create a SECOND alphabet that is organised so that alfa2[n] is the encoded form of alfa[n]. In your example, the second alphabet would be just shifted by two characters but you could also randomly shuffle the characters or use some other pattern to order them. All of this would continue to work with other alphabets such as Greek, Cyrillic, etc.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
1

I've only just started learning Python, so I have no idea how efficient this is compared to the other methods, but it works. Also, it doesn't matter whether the text is upper case, lower case or if there is any punctuation etc.

If you want to change all letters:

from string import maketrans

textin = "abcdefghijklmnopqrstuvwxyz"
textout = "cdefghijklmnopqrstuvwxyzab"
texttrans = maketrans(textin, textout)

text = "qcc, gr umpiq"

print text.translate(texttrans)

Also works to change some characters:

from string import maketrans

textin = "81972"
textout = "Seios"
texttrans = maketrans(textin, textout)

text = "811, 9t w7rk2"

print text.translate(texttrans)
JamesCraig
  • 11
  • 1
0

Here's a catch all method that might be useful for someone...

def alphabet(arg, return_lower=True):

    """
        Indexing the english alphabet consisting of 26 letters. 
        Note: zero indexed

            example usage:

                alphabet('a')
                >> 0

                alphabet(25, return_lower=False)
                >> 'Z'

        :param arg: Either type int or type chr specifying the \
                    index of desired letter or ther letter at \
                    the desired index respectivley.
        :param return_lower: If index is passes, returns letter \
                         with corresponding case. Default is \
                         set to True (lower case returned). 
        :returns: integer representing index of passed character \
                    or character at passed index.
    """

    arg = str(arg)
    assert arg.isdigit() or arg.isalpha()

    if arg.isdigit():
        if return_lower:
            return chr(int(arg) + 97).lower()  
        return chr(int(arg) + 97).upper()

    return ord(arg.lower()) - 97
LJ Brown
  • 59
  • 1
  • 2
0

Equivalent of COLUMN function in excel

def position(word):
    if len(word)>1:
        pos = 0
        for idx, letter in enumerate(word[::-1]):
            pos += (position(letter)+(1 if idx!=0 else 0))*26**(idx)
        return pos
    return ord(word.lower()) - 97


print(position("A")) --> 0
print(position("AA")) --> 26
print(position("AZ")) --> 51
gouzmi
  • 11
  • 1