Worthwhile to reverse a dictionary

R

rudysanford

I just started messing with programming and started with Python. Part
of my first project deals with translating numerical values to letters.
I would like to be able to do the reverse as well, letters to numbers,
sort of a table for lookup and a table for reverse lookup. I thought
that a dictionary would be the structure to use- write it once and in a
second instance swap the keys for values and values for keys. However,
reversing a dictionary does not seem to be easily achieved. Am I using
the wrong data structure?
 
W

Will McGugan

I just started messing with programming and started with Python. Part
of my first project deals with translating numerical values to letters.
I would like to be able to do the reverse as well, letters to numbers,
sort of a table for lookup and a table for reverse lookup. I thought
that a dictionary would be the structure to use- write it once and in a
second instance swap the keys for values and values for keys. However,
reversing a dictionary does not seem to be easily achieved. Am I using
the wrong data structure?

There may be a better solution to your original problem (if you post
more details Im sure there will be plenty of suggestions), but the
following should reverse a dictionary..
testdict.iteritems() )

Will McGugan
 
R

rudysanford

Thanks so much. That seems to have it. This is the sort of thing I
had before:


#!/usr/local/bin/python



# make a short dictionary
d1 = {'A' : '1', 'B' : '2', 'C' : '3'}

for letter in d1.keys(): print letter, '\t', d1[letter]

# make a space between the output of the 2 dictionaries
print '\n'


# reverse the keys and values from the first dictionary
# from this point many things were tried, about the best I achieved was
# getting the last key/value pair as displayed when printing the d1
# it was properly reversed but there was only one pair
d2 = {d1[letter] : letter}

for num in d2.keys(): print num, '\t', d2[num]


This displays
A 1
C 3
B 2

2 B
 
R

rudysanford

What is the difference between

" d1 = {'A' : '1', 'B' : '2', 'C' : '3'} "

and

" d1 = dict(A = 1, B = 2, C = 3) " ?

All of the dictionary examples I saw (python.org, aspn.activestate.com,
Learning Python by Lutz, among others) use d={'x' : 'y'}.
 
E

Erik Max Francis

What is the difference between

" d1 = {'A' : '1', 'B' : '2', 'C' : '3'} "

and

" d1 = dict(A = 1, B = 2, C = 3) " ?

All of the dictionary examples I saw (python.org, aspn.activestate.com,
Learning Python by Lutz, among others) use d={'x' : 'y'}.

In the latter case the values are ints, whereas in the former they are
strings. But you probably didn't mean that; indeed it is the case that

d1 = {'A': 1, 'B': 2, 'C': 3}

and

d2 = dict(A=1, B=2, C=3)

are equivalent.
 
R

rudysanford

Thanks. That is exactly what I meant.

In d2, A is not 'A' because it is being set to 1, whereas in d1, using
A instead of 'A' means A is an undeclared variable instead of a string?
 
M

Mike Meyer

Erik Max Francis said:
In the latter case the values are ints, whereas in the former they are
strings. But you probably didn't mean that; indeed it is the case that
d1 = {'A': 1, 'B': 2, 'C': 3}
and
d2 = dict(A=1, B=2, C=3)
are equivalent.

Not quite:
.... a = {'a': 1, 'b': 2}
.... b = dict(a = 1, b = 2)
.... 2 0 BUILD_MAP 0
3 DUP_TOP
4 LOAD_CONST 1 ('a')
7 LOAD_CONST 2 (1)
10 ROT_THREE
11 STORE_SUBSCR
12 DUP_TOP
13 LOAD_CONST 3 ('b')
16 LOAD_CONST 4 (2)
19 ROT_THREE
20 STORE_SUBSCR
21 STORE_FAST 0 (a)

3 24 LOAD_GLOBAL 1 (dict)
27 LOAD_CONST 1 ('a')
30 LOAD_CONST 2 (1)
33 LOAD_CONST 3 ('b')
36 LOAD_CONST 4 (2)
39 CALL_FUNCTION 512
42 STORE_FAST 1 (b)
45 LOAD_CONST 0 (None)
48 RETURN_VALUE


The first form builds the dict in place, and assigns the result. The
second form invokes the "dict" object on the keyword arguments, which
function then builds the dict. They have the same effect, provided no
one has shadowed the definition of the builtin "dict" function.

<mike
 
K

Kent Johnson

What is the difference between

" d1 = {'A' : '1', 'B' : '2', 'C' : '3'} "

and

" d1 = dict(A = 1, B = 2, C = 3) " ?

All of the dictionary examples I saw (python.org, aspn.activestate.com,
Learning Python by Lutz, among others) use d={'x' : 'y'}.

The second form is only available in Python 2.3 and newer, so any example that is older
than that will use the first form.

Kent
 
L

Larry Bates

I just started messing with programming and started with Python. Part
of my first project deals with translating numerical values to letters.
I would like to be able to do the reverse as well, letters to numbers,
sort of a table for lookup and a table for reverse lookup. I thought
that a dictionary would be the structure to use- write it once and in a
second instance swap the keys for values and values for keys. However,
reversing a dictionary does not seem to be easily achieved. Am I using
the wrong data structure?
This doesn't really answer your question (others have already done this),
but back in the 'ol days we did this:
letters=['a','b','c']
map(lambda x: ord(x)-64, letters)
[1, 2, 3]

This takes advantage of the fact that letters must be stored as
binary integers in ASCII (e.g. 'a' = 65, 'b'=66, etc.). You can
go the other direction with chr(x). Not completely sure about
what you want to accomplish, but this eliminates the need for
the dictionaries.

Larry Bates
 
R

rudysanford

The end of what I was trying to do was encode and decode using ITA2
International Telegraph Alphabet 2, more commonly called Baudot. It
uses 5 bit binary but with the use of a shift up or a shift down can
utilize 2 tables of 32- one for letters one for figures.

A better explanation of ITA2 here: http://en.wikipedia.org/wiki/Baudot

It occurred to me that rather than writing for four data dictionaries
(bin to ltrs, bin to figs, figs, to bin, figs to letters), I could just
swap the dictionary key/value pairs around.

It seems that I have more reading to do. I have not gotten to lambda
formations yet.
 
D

Dennis Lee Bieber

It occurred to me that rather than writing for four data dictionaries
(bin to ltrs, bin to figs, figs, to bin, figs to letters), I could just
swap the dictionary key/value pairs around.
Why bother with a dictionary at all... Just use a simple string (or
two) containing the characters found in Baudot, positioned such that an
index into the string returns the Baudot numeric value. [you'll need
special treatment for the shift codes, and to detect the "invalid entry"
spots, I'm using ~ for that]

As a make-believe (I've not bothered to look up the Baudot system)

ltrs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ \n\r<>" #31 + 1 for FIGS
fgrs = "0123456789.,;:'"!@#$%^&*()-+_=/" #31 + 1 for LTRS

MODE = ltrs

def toBaudot(istr):
global MODE
bout = []
for c in istr:
if c == FIGS_SHIFT:
MODE = fgrs
bout.append(ord(FIGS_SHIFT))
elif c == LTRS_SHIFT:
MODE = ltrs
bout.append(ord(LTRS_SHIFT))
else:
b = MODE.find(c) #returns -1 if c is not in mode
bout.append(b)
return bout

def toString(bin):
global MODE
chars = []
for b in bin:
if b == ord(FIGS_SHIFT):
MODE = fgrs
chars.append(FIGS_SHIFT)
elif b == ord(LTRS_SHIFT):
MODE = ltrs
chars.append(LTRS_SHIFT)
else:
if -1 < b < len(MODE):
chars.append(MODE)
else:
chars.append("~")
return "".join(chars)

--
 
C

crc

I assume your talking about building a new dictionary with the key an
value pair switched. I have seen no built in function to do this but
have found a way to create another dictionary that is the inverse o
the first.

for example you have designed a dictionary such as

a={}
a['one']=1
a['two']=2
a['three']=3
a['four']=4

when your redy to build a revers dictionary you semply do the folowing
b={}
for x in a:
temp_idx=a[x]
b[temp_idx]=x

now you get
{'four': 4, 'three': 3, 'two': 2, 'one': 1}
for a

and

{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
for
 
M

Mike Meyer

crc said:
I assume your talking about building a new dictionary with the key and
value pair switched. I have seen no built in function to do this but I
have found a way to create another dictionary that is the inverse of
the first.

Note that you can't reliable "reverse" a dictionary. That's because
you can put anything in a dictionary, but some things can't be used as
keys to a dictionary.
when your redy to build a revers dictionary you semply do the folowing
b={}
for x in a:
temp_idx=a[x]
b[temp_idx]=x

You can do it with a single list comprehension:

b = dict([(x, y) for y, x in a.iteritems()])

<mike
 
A

Alex Martelli

Mike Meyer said:
Note that you can't reliable "reverse" a dictionary. That's because
you can put anything in a dictionary, but some things can't be used as
keys to a dictionary.

That's reason #1. Reason #2 is that you can have duplicates among a
dict's values, but not among its keys. So, a simply and correctly
reversable dict is one whose values are all hashable and unique -- in
terms of EQUALITY (which is stricter than demanding uniqueness in terms
of IDENTITY), e.g. you can't have both 1 (the integer) and 1.0 (the
float with a 0 fractional part) as values (because they're not distinct
by equality: 1 == 1.0).

If you do have a dict whose hashable values are not guaranteed to be
unique you have several choices as to how to "pseudo-reverse" it (e.g.,
"dropping", among the values in the pseudoreversed dict, all but one of
the keys that map to the same value in the original dict; or, making a
"reversoid" dict whose values are containers of all the keys mapping to
each value in the original dict).

If you have a dict whose values are not guaranteed to be hashable, and
thus can't be keys in the ``sotospeakreverse'' dict, you have to work
even harder, striving to build keys for the latter which may in some
sense (probably one meaningful only to a specific application) "stand
for" the values in the original dict. I remember only one case in a
real-world program of needing anything like that -- the original dict
had "sub"-dicts (mapping strings to numbers) as values, but fortunately
it was acceptable for the application to have frozen sets of (key,
value) pairs "stand for" those subsets in the "reversoid" dict (I sure
did wish at the time I had "frozen dicts", though;-).


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top