views:

157

answers:

8

I want to assign a value to each letter in the alphabet, so that a -> 1, b -> 2, c -> 3, ... z -> 26. Something like a function which returns the value of the letter, for example:

value('a') = 1

value('b') = 2

etc...

How would I go about doing this in python?

+2  A: 

Use a dictionary for key:value pairs. Although for a simple mapping like this there are probably some clever ways of doing this.

Fabian
Skip the cleverness - `dict` is the right way to go.
Paul McGuire
+3  A: 

If you just want to map characters of the ASCII alphabet to numbers, you can use ord() and then adjust the result:

>>> ord('a') - 96
1

If you want this to work for uppercase letters too:

>>> ord('A'.lower()) - 96
1

Also, you might want to validate that the argument is indeed a single ASCII character:

>>> char = 'a'
>>> len(char) == 1 and char.isalpha() and 'a' <= char <= 'z'
True

Or:

>>> import string
>>> len(char) == 1 and char in string.ascii_lowercase
True
Ben James
+2  A: 
def value(letter):
    return ord(letter) - ord('a') + 1
Ned Batchelder
This seems more sensible than a `dict` to me, but would want some range checking, case checking, etc.
Johnsyweb
Really, Ned? I mean, this was the state of the art in C back in the 70's, but Python *does* have dict as a native, built-in, optimized data structure. With a dict, the OP can further assign the same or different codes to the upper case values; special codes for punctuation; and can check for validity with `if ch in ch2valuedict:` instead of nasty old `if ord('a') <= ch <= ord('z'):` etc. Our Python has dicts, we should use them, and we should lead beginners to them when they are so appropriate.
Paul McGuire
@Paul, the question was pretty sparse on details, but it did include the word "function". It's easy to invent requirements not mentioned by the OP, and to decide that a dictionary is the best approach. But it might be that his next need is to do "the same thing" for Chinese. You might be right, if we knew more about the entire system being built, a dictionary might be the best approach. But looking just at the question asked, I think a simple function like this is very reasonable.
Ned Batchelder
@Paul McGuire: tzk, tzk - pray tell, in which language does this `if ord('a') <= ch <= ord('z'):` work? 'cause it ain't Python. Not if ch is a single-char string.
Nas Banov
@Nas - oof, I've been working in C lately, and some of it leaked into the Python part of my brain!
Paul McGuire
A: 

You should exploit the fact that 'a', 'b', etc. have ASCII values behind them.

ord('a') # this returns int 97
ord('b') # this returns int 98

Therefore, you could do something like:

ord(letter) - ord('a') + 1 # e.g., a: 97 - 97 + 1 = 1
orangeoctopus
A: 

Why not just make a list of each letter in the alphabet and then use the index values as the return value

Jordan
A: 

How about this?

import string
value = lambda x: string.ascii_lowercase.index(x) + 1

In [1]: value("a")
Out[1]: 1
piquadrat
Ewwww! Really?!
Nas Banov
+3  A: 

You want a native python dictionary.

(and you probably also want your values to start from"0" not from "1" , so you can void adding a +1 on all your mappings, as bellow)

Build one with this:

import string
values = dict()
for index, letter in enumerate(string.ascii_lowercase):
   values[letter] = index + 1

This give syou things like:

print values["a"]
-> 1

Of course, you probably could use the "ord" built-in function and skip this dictionary altogether, as in the other answers:

print ord("c") - (ord("a")) + 1

Or in python 3.x or 2.7, you can create the dicionary in a single pass with a dict generator expression:

values = {chr(i): i + 1 for i in range(ord("a"), ord("a") + 26)}
jsbueno
you can use `enumerate(string.ascii_lowercase,1)` to avoid having to add `1` to `index` in the loop
gnibbler
+2  A: 
from itertools import count
from string import lowercase
value = dict(zip(lowercase, count(1))).get
Gavin Panella